home *** CD-ROM | disk | FTP | other *** search
/ OctaMED Sound Studio 1 / OctaMED SoundStudio V1.iso / soundstudio v1 / programmers / promixplayer.a < prev    next >
Text File  |  1996-06-18  |  87KB  |  3,334 lines

  1. ;============================================================================
  2. ;    promixplayer.a
  3. ;    ~~~~~~~~~~~~~~
  4. ; $VER: promixplayer 7.1 (14.6.1996)
  5. ;
  6. ; The music player routine for MMD2/MMD3 OctaMED
  7. ; 1-64 channel modules using the mixing mode.
  8. ;
  9. ; Copyright © 1995-1996 Teijo Kinnunen and RBF Software.
  10. ;
  11. ; Written by Teijo Kinnunen.
  12. ; Technical comments/questions/bug reports can be sent to:
  13. ;    Teijo Kinnunen
  14. ;    Oksantie 19
  15. ;    FIN-86300  OULAINEN
  16. ;    FINLAND
  17. ;    email: Teijo.Kinnunen@oulu.fi
  18. ;
  19. ; See OctaMED docs for conditions about using these routines.
  20. ; Comments/questions about distribution and usage conditions
  21. ; should be directed to RBF Software. 
  22. ;
  23. ; (Email: rbfsoft@octamed.co.uk   or  rbfsoft@cix.compulink.co.uk)
  24. ;
  25. ;============================================================================
  26.  
  27. ;****** Feature control ******
  28. ;
  29. MIDI        EQU 0    ;1 = include MIDI code
  30. AUDDEV        EQU 1    ;1 = allocate channels using audio.device
  31. SYNTH        EQU 1    ;1 = include synth-sound handler
  32. CHECK        EQU 1    ;1 = do range checkings (track, sample in mem etc.)
  33. RELVOL        EQU 1    ;1 = include relative volume handling code
  34. HOLD        EQU 1    ;1 = handle hold/decay
  35. ;
  36. ; The less features you include, the faster and shorter the play-routine
  37. ; will be.
  38. ;
  39.  
  40. ;============================================================================
  41.  
  42.         INCLUDE    "chinfo.i"
  43.  
  44. ; The MMD structure offsets
  45. mmd_id        EQU    0
  46. mmd_modlen    EQU    4
  47. mmd_songinfo    EQU    8
  48. ; these two for MMD2s only!
  49. mmd_psecnum    EQU    12
  50. mmd_pseq    EQU    14
  51. ;
  52. mmd_blockarr    EQU    16
  53. mmd_smplarr    EQU    24
  54. mmd_expdata    EQU    32
  55. mmd_pstate    EQU    40 ; <0 = play song, 0 = don't play, >0 = play block
  56. mmd_pblock    EQU    42
  57. mmd_pline    EQU    44
  58. mmd_pseqnum    EQU    46
  59. mmd_counter    EQU    50
  60. mmd_songsleft    EQU    51
  61.  
  62.         INCLUDE    "medtrkdata.i"
  63.  
  64. ; Instrument data
  65. inst_repeat    EQU    0
  66. inst_replen    EQU    2
  67. inst_midich    EQU    4
  68. inst_midipreset    EQU    5
  69. inst_svol    EQU    6
  70. inst_strans    EQU    7
  71.  
  72. ; Audio hardware offsets
  73. ac_ptr    EQU    $00
  74. ac_len    EQU    $04
  75. ac_per    EQU    $06
  76. ac_vol    EQU    $08
  77.  
  78. AUDIO_CONST    EQU    3579545
  79.  
  80. ; Maximum number of tracks allowed. If you don't need this much tracks,
  81. ; you can decrease the number to save some space. (Be sure that the
  82. ; song really has no more than MAX_NUMTRACKS tracks. Minimum allowed
  83. ; value = 4.)
  84. MAX_NUMTRACKS    EQU    64
  85.  
  86. ; This value is used for MMD0/1 conversion. If MAX_NUMTRACKS <= 16,
  87. ; this should be the same. If MAX_NUMTRACKS > 16, this should be 16.
  88. MAX_MMD1_TRACKS    EQU    16
  89.  
  90.         SECTION    "text",CODE
  91.  
  92. ; -------- _ChannelOff: Turn off a channel -------------------------------
  93. _ChannelOff:    ;d0 = channel #
  94.         lea    DB,a0
  95.         lea    trackdataptrs-DB(a0),a1
  96.         lsl.w    #2,d0
  97.         adda.w    d0,a1
  98.         lsr.w    #2,d0
  99.         movea.l    (a1),a1
  100.         move.b    trk_outputdev(a1),d1
  101.         bne.s    choff_exit
  102.     IFNE    MIDI
  103.         move.b    trk_prevmidin(a1),d1    ;first: is it MIDI??
  104.         bne.s    choff_ismidi    ;not a midi note
  105.     ENDC
  106.         move.l    d7,-(sp)
  107.         move.w    d0,d7
  108.         movea.l    a1,a5
  109.         XREF    _ChOff_mix
  110.         jsr    _ChOff_mix(pc)
  111.         move.l    (sp)+,d7
  112. ; -------- TURN OFF AMIGA-CHANNEL ----------------------------------------
  113.     IFNE    SYNTH
  114.         clr.l    trk_synthptr(a1)
  115.         clr.b    trk_synthtype(a1)
  116.     ENDC
  117.         clr.w    trk_soffset(a1)
  118. choff_exit    rts
  119.         
  120.     IFNE    MIDI
  121. ; -------- TURN OFF MIDI TRACK -------------------------------------------
  122. choff_ismidi    lea    noteondata-DB(a0),a0
  123. choff_midi:    clr.b    trk_prevmidin(a1)
  124.         move.b    d1,1(a0)
  125.         bmi.s    choff_exit
  126.         move.b    trk_prevmidich(a1),(a0)    ;prev midi channel
  127.         clr.b    2(a0)
  128.         or.b    #$90,(a0)        ;note off
  129.         moveq    #3,d0
  130.         bra.w    _AddMIDIData
  131.     ENDC
  132.  
  133. ; -------- SoundOff: Turn off all channels -------------------------------
  134. SoundOff:    movem.l    d2/a5,-(sp)
  135.         moveq    #MAX_NUMTRACKS-1,d2
  136. SO_loop0    move.l    d2,d0
  137.         bsr.s    _ChannelOff
  138.         dbf    d2,SO_loop0
  139.         clr.l    _module        ;play nothing
  140.         movem.l    (sp)+,d2/a5
  141. SO_rts        rts
  142.  
  143. ; -------- _PlayNote: The note playing routine ---------------------------
  144. _PlayNote:    ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
  145. ; -------- CHECK INSTRUMENT (existence, type) ----------------------------
  146.         move.l    a3,d4
  147.         beq.s    SO_rts
  148.         moveq    #0,d4
  149.         bset    d7,d4    ;d4 is mask for this channel
  150.         movea.l    mmd_smplarr(a2),a0
  151.         add.w    d3,d3            ;d3 = instr.num << 2
  152.         add.w    d3,d3
  153.         move.l    0(a0,d3.w),d5        ;get address of instrument
  154.     IFNE    MIDI
  155.         bne.s    inmem
  156.         tst.b    inst_midich(a3)        ;is MIDI channel set?
  157.     ENDC
  158.     IFNE    CHECK
  159.         beq.w    pnote_rts        ; NO!!!
  160.     ENDC
  161. ; -------- ADD TRANSPOSE -------------------------------------------------
  162. inmem        add.b    msng_playtransp(a4),d1    ;add play transpose
  163.         add.b    inst_strans(a3),d1    ;and instr. transpose
  164.         move.b    trk_outputdev(a5),d3
  165.         beq.s    pn_offami
  166.         bra.s    noprevmidi        ;dunno.. unsupported type
  167.     
  168. ; -------- TURN OFF CHANNEL DMA, IF REQUIRED -----------------------------
  169. pn_offami    cmp.w    maxaudiotrk-DB(a6),d7
  170.         bge.s    nodmaoff
  171.         move.l    d5,a1
  172.     IFNE    SYNTH
  173.         tst.l    d5
  174.         beq.s    stpdma
  175.         tst.b    trk_synthtype(a5)
  176.         ble.s    stpdma        ;prev. type = sample/hybrid
  177.         cmp.w    #-1,4(a1)    ;type == SYNTHETIC??
  178.         beq.s    nostpdma
  179.     ENDC
  180. stpdma:        move.w    d1,-(sp)
  181.         XREF    _MixPrepSynth
  182.         jsr    _MixPrepSynth(pc)
  183.         move.w    (sp)+,d1
  184. nostpdma:
  185.     IFNE    SYNTH
  186.         clr.l    trk_synthptr(a5)
  187.     ENDC
  188. nodmaoff:    subq.b    #1,d1
  189.     IFNE    MIDI
  190. ; -------- KILL PREVIOUS MIDI NOTE ---------------------------------------
  191.         move.b    trk_prevmidin(a5),d3    ;get prev. midi note
  192.         beq.s    noprevmidi
  193.         clr.b    trk_prevmidin(a5)
  194.         lea    noteondata+2-DB(a6),a0
  195.         clr.b    (a0)
  196.         move.b    d3,-(a0)
  197.         bmi.s    noprevmidi
  198.         move.b    trk_prevmidich(a5),-(a0) ;prev midi channel
  199.         or.b    #$90,(a0)         ;note off
  200.         move.w    d1,-(sp)
  201.         moveq    #3,d0
  202.         bsr.w    _AddMIDId
  203.         move.w    (sp)+,d1
  204. noprevmidi
  205. ; -------- IF MIDI NOTE, CALL MIDI NOTE ROUTINE --------------------------
  206.         tst.b    inst_midich(a3)
  207.         bne.w    handleMIDInote
  208.     ENDC
  209. ; -------- TEST OUTPUT DEVICE AND BRANCH IF NOT STD ----------------------
  210.     IFEQ    MIDI
  211. noprevmidi
  212.     ENDC
  213. ; -------- SET SOME AMIGA-CHANNEL PARAMETERS -----------------------------
  214.     IFNE    CHECK
  215.         cmp.w    maxaudiotrk-DB(a6),d7
  216.         bge.w    pnote_rts    ;no Amiga instruments here!!!
  217.     ENDC
  218.     IFNE    HOLD
  219.         clr.b    trk_fadespd(a5)        ;no fade yet..
  220.         move.b    trk_initdecay(a5),trk_decay(a5)    ;set decay
  221.     ENDC
  222.         clr.w    trk_vibroffs(a5)    ;clr vibrato/tremolo offset
  223.         move.l    d5,a0
  224.     IFNE    SYNTH
  225. ; -------- IF SYNTH NOTE, CALL SYNTH ROUTINE -----------------------------
  226.         tst.w    4(a0)
  227.         bmi.w    handleSynthnote
  228.         clr.b    trk_synthtype(a5)
  229.     ENDC
  230.         XREF    _PlayNoteMix
  231. pn_hybrid    jsr    _PlayNoteMix(pc)
  232.     IFNE    SYNTH
  233.         tst.b    trk_synthtype(a5)
  234.         bne.w    hSn2
  235.     ENDC
  236. pnote_rts    rts
  237.  
  238. handlenonstdout
  239.         rts
  240.  
  241.     IFNE    MIDI
  242. ; -------- MIDI NOTE PLAYER ROUTINE --------------------------------------
  243. handleMIDInote:
  244. ; -------- CHECK & SCALE VOLUME ------------------------------------------
  245.         move.b    trk_prevvol(a5),d2 ;temporarily save the volume
  246.     IFNE    RELVOL
  247. ; -------- GetRelVol: Calculate track volume -----------------------------
  248.         ext.w    d2
  249.         mulu    trk_trackvol(a5),d2
  250.         lsr.w    #7,d2
  251.     ENDC
  252.     IFEQ    RELVOL
  253.         lsl.b    #1,d2
  254.     ENDC
  255.         subq.b    #1,d2        ;if 128 => 127
  256.         bpl.s    hmn_notvolu0
  257.         moveq    #0,d2
  258. hmn_notvolu0
  259.         moveq    #0,d5
  260. ; -------- CHECK MIDI CHANNEL --------------------------------------------
  261.         move.b    inst_midich(a3),d5 ;get midi chan of this instrument
  262.         bpl.s    hmn_nosmof    ;bit 7 clear
  263.         clr.b    trk_prevmidin(a5)    ;suppress note off!
  264.         bra.s    hmn_smof
  265. hmn_nosmof    move.b    d1,trk_prevmidin(a5)
  266. hmn_smof    and.b    #$1F,d5        ;clear all flag bits etc...
  267.         subq.b    #1,d5        ;from 1-16 to 0-15
  268.         move.b    d5,trk_prevmidich(a5)    ;save to prev midi channel
  269.  
  270. ; -------- CHECK MIDI PRESET ---------------------------------------------
  271.         moveq    #0,d0
  272.         move.b    trk_previnstr(a5),d0
  273.         add.w    d0,d0
  274.         lea    ext_midipsets-DB(a6),a1
  275.         move.w    0(a1,d0.w),d0    ;get preset #
  276.         beq.s    nochgpres    ;zero = no preset
  277.         lea    prevmidicpres-DB(a6),a1
  278.         adda.w    d5,a1
  279.         adda.w    d5,a1
  280.         cmp.w    (a1),d0        ;is this previous preset ??
  281.         beq.s    nochgpres    ;yes...no need to change
  282.         move.w    d0,(a1)        ;save preset to prevmidicpres
  283.         subq.w    #1,d0        ;sub 1 to get 0 - 127
  284.         btst    #6,inst_midich(a3)
  285.         bne.s    hmn_extpreset
  286. ; -------- PREPARE PRESET CHANGE COMMAND ---------------------------------
  287. hmn_ordpreset    lea    preschgdata+1-DB(a6),a0
  288.         move.b    d0,(a0)        ;push the number to second byte
  289.         moveq    #2,d0
  290. hmn_sendpreset    move.b    #$c0,-(a0)    ;command: $C
  291.         or.b    d5,(a0)        ;"or" midi channel
  292.         move.w    d1,-(sp)
  293.         bsr.w    _AddMIDId
  294.         move.w    (sp)+,d1
  295.         tst.b    d2
  296.         beq.s    hmn_suppress    ;vol = 0, don't send NOTE ON
  297.  
  298. ; -------- PREPARE & SEND NOTE ON COMMAND --------------------------------
  299. nochgpres    lea    bytesinnotebuff-DB(a6),a0
  300.         movea.l    a0,a1
  301.         adda.w    (a0)+,a0
  302.         or.b    #$90,d5        ;MIDI: Note on
  303.         move.b    d5,(a0)+    ;MIDI msg Note on & channel
  304.         move.b    d1,(a0)+    ;MIDI msg note #
  305.         move.b    d2,(a0)        ;MIDI msg volume
  306.         beq.s    hmn_suppress    ;vol = 0 -> no note
  307.         addq.w    #3,(a1)
  308.         rts
  309. hmn_suppress    st    trk_prevmidin(a5)
  310.         rts
  311.  
  312. ; -------- HANDLE EXTENDED PRESET ----------------------------------------
  313. hmn_extpreset    cmp.w    #100,d0
  314.         blt.s    hmn_ordpreset
  315.         moveq    #99,d3
  316. hmn_loop100    sub.w    #100,d0
  317.         addq.b    #1,d3
  318.         cmp.w    #100,d0
  319.         bge.s    hmn_loop100
  320.         lea    preschgdata+2-DB(a6),a0
  321.         move.b    d0,(a0)        ;push the <= 99 number
  322.         move.b    d3,-(a0)    ;push the >= 100 number
  323.         moveq    #3,d0
  324.         bra.s    hmn_sendpreset
  325.     ENDC
  326.  
  327.     IFNE    SYNTH
  328. ; -------- TRIGGER SYNTH NOTE, CLEAR PARAMETERS --------------------------
  329. handleSynthnote    move.b    d1,trk_prevnote2(a5)
  330.         move.l    a0,trk_synthptr(a5)
  331.         cmp.w    #-2,4(a0)    ;HYBRID??
  332.         bne.s    hSn_nossn
  333.         st    trk_synthtype(a5)
  334.         movea.l    278(a0),a0    ;yep, get the waveform pointer
  335.         bra.w    pn_hybrid    ;go and play it
  336. hSn_nossn:    move.b    #1,trk_synthtype(a5)
  337.         lea    _freq_tables+32-DB(a6),a1
  338.         move.b    trk_finetune(a5),d0    ;finetune value
  339.         add.b    d0,d0
  340.         add.b    d0,d0        ;multiple by 4...
  341.         ext.w    d0        ;extend
  342.         movea.l    0(a1,d0.w),a1    ;period table address
  343.         move.l    a1,trk_periodtbl(a5) ;save table ptr for synth periods
  344.         add.w    d1,d1
  345.         move.w    0(a1,d1.w),d1
  346.         move.w    d1,trk_prevper(a5)
  347.         clr.l    trk_sampleptr(a5)
  348. hSn2:        lea    trk_arpgoffs(a5),a1
  349.         clr.l    (a1)+
  350.         clr.l    (a1)+
  351.         btst    #0,trk_miscflags(a5)
  352.         bne.s    hSn_cmdE ;cmd E given, don't clear trk_wfcmd!
  353.         clr.w    (a1)
  354. hSn_cmdE    addq.l    #2,a1
  355.         clr.w    (a1)+
  356.         clr.l    (a1)+
  357.         clr.l    (a1)+
  358.         clr.l    (a1)+
  359.         move.l    #sinetable,(a1)+
  360.         clr.w    (a1)+
  361.         movea.l    trk_synthptr(a5),a0
  362.                 move.w    18(a0),(a1)+
  363.                 clr.b    (a1)
  364.         moveq    #64,d4
  365.         rts
  366.  
  367. synth_start    move.w    trk_prevper(a5),d5
  368. synth_start2    move.l    d0,a0
  369. ; -------- SYNTHSOUND VOLUME SEQUENCE HANDLING ---------------------------
  370.         subq.b    #1,trk_volxcnt(a5)    ;decrease execute counter..
  371.         bgt.w    synth_wftbl        ;not 0...go to waveform
  372.         move.b    trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  373.         move.b    trk_volchgspd(a5),d0    ;volume change??
  374.         beq.s    synth_nochgvol        ;no.
  375.         add.b    trk_synvol(a5),d0    ;add previous volume
  376.         bpl.s    synth_voln2l        ;not negative
  377.         moveq    #0,d0            ;was negative => 0
  378. synth_voln2l    cmp.b    #$40,d0            ;too high??
  379.         ble.s    synth_voln2h        ;not 2 high.
  380.         moveq    #$40,d0            ;was 2 high => 64
  381. synth_voln2h    move.b    d0,trk_synvol(a5)    ;remember new...
  382. synth_nochgvol    move.l    trk_envptr(a5),d1    ;envelope pointer
  383.         beq.s    synth_novolenv
  384.         movea.l    d1,a1
  385.         move.b    (a1)+,d0
  386.         add.b    #128,d0
  387.         lsr.b    #2,d0
  388.         move.b    d0,trk_synvol(a5)
  389.         addq.b    #1,trk_envcount(a5)
  390.         bpl.s    synth_endenv
  391.         clr.b    trk_envcount(a5)
  392.         move.l    trk_envrestart(a5),a1
  393. synth_endenv    move.l    a1,trk_envptr(a5)
  394. synth_novolenv    move.w    trk_volcmd(a5),d0    ;get table position ptr
  395.         tst.b    trk_volwait(a5)        ;WAI(t) active
  396.         beq.s    synth_getvolcmd        ;no
  397.         subq.b    #1,trk_volwait(a5)    ;yep, decr wait ctr
  398.         ble.s    synth_getvolcmd        ;0 => continue
  399.         bra.w    synth_wftbl        ;> 0 => still wait
  400. synth_inccnt    addq.b    #1,d0
  401. synth_getvolcmd    addq.b    #1,d0            ;advance pointer
  402.         move.b    21(a0,d0.w),d1        ;get command
  403.         bmi.s    synth_cmd        ;negative = command
  404.         move.b    d1,trk_synvol(a5)    ;set synthvol
  405.         bra.w    synth_endvol        ;end of volume executing
  406. synth_cmd    and.w    #$000f,d1
  407.         add.b    d1,d1
  408.         move.w    synth_vtbl(pc,d1.w),d1
  409.         jmp    syv(pc,d1.w)
  410. synth_vtbl    dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  411.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  412.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  413.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  414.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  415. ; -------- VOLUME SEQUENCE COMMANDS --------------------------------------
  416. syv
  417. syv_fe        move.b    22(a0,d0.w),d0        ;JMP
  418.         bra.s    synth_getvolcmd
  419. syv_f0        move.b    22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  420.         bra.s    synth_inccnt
  421. syv_f1        move.b    22(a0,d0.w),trk_volwait(a5)    ;WAI(t)
  422.         addq.b    #1,d0
  423.         bra.s    synth_endvol
  424. syv_f3        move.b    22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  425.         bra.s    synth_inccnt
  426. syv_f2        move.b    22(a0,d0.w),d1
  427.         neg.b    d1
  428.         move.b    d1,trk_volchgspd(a5) ;set volume slide down
  429.         bra.s    synth_inccnt
  430. syv_fa        move.b    22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  431.         clr.b    trk_wfwait(a5)
  432.         bra.s    synth_inccnt
  433. syv_f4        move.b    22(a0,d0.w),d1
  434.         bsr.s    synth_getwf
  435.         clr.l    trk_envrestart(a5)
  436. syv_f4end    move.l    a1,trk_envptr(a5)
  437.         clr.b    trk_envcount(a5)
  438.         bra.w    synth_inccnt
  439. syv_f5        move.b    22(a0,d0.w),d1
  440.         bsr.s    synth_getwf
  441.         move.l    a1,trk_envrestart(a5)
  442.         bra.s    syv_f4end
  443. syv_f6        clr.l    trk_envptr(a5)
  444.         bra.w    synth_getvolcmd
  445. synth_getwf    ext.w    d1    ;d1 = wform number, returns ptr in a1
  446.         add.w    d1,d1    ;create index
  447.         add.w    d1,d1
  448.         lea    278(a0),a1
  449.         adda.w    d1,a1
  450.         movea.l    (a1),a1        ;get wform address
  451.         addq.l    #2,a1        ;skip length
  452.         rts
  453. syv_ff        subq.b    #1,d0
  454. synth_endvol    move.w    d0,trk_volcmd(a5)
  455. synth_wftbl    moveq    #0,d0
  456.         move.b    trk_synvol(a5),d0
  457.         moveq    #0,d1
  458.         move.b    trk_prevvol(a5),d1
  459.         mulu    d0,d1
  460.         asr.w    #6,d1
  461.         move.b    d1,trk_tempvol(a5)
  462.         adda.w    #158,a0
  463. ; -------- SYNTHSOUND WAVEFORM SEQUENCE HANDLING -------------------------
  464.         subq.b    #1,trk_wfxcnt(a5)    ;decr. wf speed counter
  465.         bgt.w    synth_arpeggio        ;not yet...
  466.         move.b    trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  467.         move.w    trk_wfcmd(a5),d0    ;get table pos offset
  468.         move.w    trk_wfchgspd(a5),d1    ;CHU/CHD ??
  469.         beq.s    synth_tstwfwai        ;0 = no change
  470. wytanwet    add.w    trk_perchg(a5),d1    ;add value to current change
  471.         move.w    d1,trk_perchg(a5)    ;remember amount of change
  472. synth_tstwfwai    tst.b    trk_wfwait(a5)        ;WAI ??
  473.         beq.s    synth_getwfcmd        ;not waiting...
  474.         subq.b    #1,trk_wfwait(a5)    ;decr wait counter
  475.         beq.s    synth_getwfcmd        ;waiting finished
  476.         bra.w    synth_arpeggio        ;still sleep...
  477. synth_incwfc    addq.b    #1,d0
  478. synth_getwfcmd    addq.b    #1,d0            ;advance position counter
  479.         move.b    -9(a0,d0.w),d1        ;get command
  480.         bmi.s    synth_wfcmd        ;negative = command
  481.         ext.w    d1
  482.         add.w    d1,d1
  483.         add.w    d1,d1
  484.         movea.l    120(a0,d1.w),a1
  485. synth_setmixwf    XREF    _MixSetSynthWF
  486.         move.l    d0,-(sp)
  487.         move.l    a0,-(sp)
  488.         jsr    _MixSetSynthWF(pc)
  489.         move.l    (sp)+,a0
  490.         move.l    (sp)+,d0
  491.         bra.w    synth_wfend        ;no new commands now...
  492. synth_wfcmd    and.w    #$000f,d1        ;get the right nibble
  493.         add.b    d1,d1            ;* 2
  494.         move.w    synth_wfctbl(pc,d1.w),d1
  495.         jmp    syw(pc,d1.w)        ;jump to command
  496. synth_wfctbl    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  497.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  498.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  499.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  500. ; -------- WAVEFORM SEQUENCE COMMANDS ------------------------------------
  501. syw
  502. syw_f7        move.b    -8(a0,d0.w),d1
  503.         ext.w    d1
  504.         add.w    d1,d1
  505.         add.w    d1,d1
  506.         movea.l    120(a0,d1.w),a1
  507.         addq.l    #2,a1
  508.         move.l    a1,trk_synvibwf(a5)
  509.         bra.s    synth_incwfc
  510. syw_fe        move.b    -8(a0,d0.w),d0        ;jump (JMP)
  511.         bra.s    synth_getwfcmd
  512. syw_fc        move.w    d0,trk_arpsoffs(a5)    ;new arpeggio begin
  513.         move.w    d0,trk_arpgoffs(a5)
  514. synth_findare    addq.b    #1,d0
  515.         tst.b    -9(a0,d0.w)
  516.         bpl.s    synth_findare
  517.         bra.s    synth_getwfcmd
  518. syw_f0        move.b    -8(a0,d0.w),trk_initwfxspd(a5)    ;new waveform speed
  519.         bra    synth_incwfc
  520. syw_f1        move.b    -8(a0,d0.w),trk_wfwait(a5)    ;wait waveform
  521.         addq.b    #1,d0
  522.         bra.s    synth_wfend
  523. syw_f4        move.b    -8(a0,d0.w),trk_synvibdep+1(a5)    ;set vibrato depth
  524.         bra.w    synth_incwfc
  525. syw_f5        move.b    -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  526.         addq.b    #1,trk_synthvibspd+1(a5)
  527.         bra.w    synth_incwfc
  528. syw_f2        moveq    #0,d1            ;set slide down
  529.         move.b    -8(a0,d0.w),d1
  530. synth_setsld    move.w    d1,trk_wfchgspd(a5)
  531.         bra.w    synth_incwfc
  532. syw_f3        move.b    -8(a0,d0.w),d1        ;set slide up
  533.         neg.b    d1
  534.         ext.w    d1
  535.         bra.s    synth_setsld
  536. syw_f6        clr.w    trk_perchg(a5)        ;reset period
  537.         move.w    trk_prevper(a5),d5
  538.         bra.w    synth_getwfcmd
  539. syw_fa        move.b    -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  540.         clr.b    trk_volwait(a5)
  541.         bra.w    synth_incwfc
  542. syw_ff        subq.b    #1,d0        ;pointer = END - 1
  543. synth_wfend    move.w    d0,trk_wfcmd(a5)
  544. ; -------- HANDLE SYNTHSOUND ARPEGGIO ------------------------------------
  545. synth_arpeggio    move.w    trk_arpgoffs(a5),d1
  546.         beq.s    synth_vibrato
  547.         moveq    #0,d0
  548.         move.b    -8(a0,d1.w),d0
  549.         add.b    trk_prevnote2(a5),d0
  550.         movea.l    trk_periodtbl(a5),a1    ;get period table
  551.         add.w    d0,d0
  552.         move.w    0(a1,d0.w),d5
  553.         addq.b    #1,d1
  554.         tst.b    -8(a0,d1.w)
  555.         bpl.s    synth_noarpres
  556.         move.w    trk_arpsoffs(a5),d1
  557. synth_noarpres    move.w    d1,trk_arpgoffs(a5)
  558. ; -------- HANDLE SYNTHSOUND VIBRATO -------------------------------------
  559. synth_vibrato    move.w    trk_perchg(a5),d1
  560.         tst.w    trk_synvibdep(a5)    ;get vibrato depth
  561.         beq.s    synth_novib        ;0 => no vibrato
  562.         move.w    trk_synviboffs(a5),d0    ;get offset
  563.         lsr.w    #4,d0            ;/ 16
  564.         and.w    #$1f,d0            ;sinetable offset (0-31)
  565.         movea.l trk_synvibwf(a5),a0
  566.         move.b    0(a0,d0.w),d0       ;get a byte
  567.         ext.w    d0            ;to word
  568.         muls    trk_synvibdep(a5),d0    ;amplify (* depth)
  569.         asr.w    #8,d0            ;and divide by 64
  570.         add.w    d0,d1            ;add vibrato...
  571.         move.w    trk_synthvibspd(a5),d0    ;vibrato speed
  572.         add.w    d0,trk_synviboffs(a5)    ;add to offset
  573. synth_novib    tst.w    d5
  574.         beq.s    synth_rtper
  575.         move.l    #AUDIO_CONST,d0
  576.         divu    d5,d0
  577.         add.w    d1,d0
  578.         beq.s    synth_rtper
  579.         move.l    #AUDIO_CONST,d5
  580.         divu    d0,d5
  581. synth_rtper    cmp.w    #113,d5            ;overflow??
  582.         bhi.s    synth_pern2h
  583.         moveq    #113,d5
  584. synth_pern2h    rts
  585.     ENDC
  586. sinetable    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  587.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  588.         dc.b    -106,-90,-71,-49,-25,0
  589.  
  590.         EVEN
  591.         XDEF    _IntHandler
  592. _IntHandler:    movem.l    d2-d7/a2-a6,-(sp)
  593.         lea    DB,a6    ;don't expect a1 to contain DB address
  594.         movea.l    _module-DB(a6),a2
  595.         move.l    a2,d0
  596.         beq.w    plr_exit
  597.     IFNE    MIDI
  598.         clr.b    lastcmdbyte-DB(a6)    ;no MIDI optimization
  599.     ENDC
  600.         tst.w    mmd_pstate(a2)
  601.         beq.w    plr_exit
  602.     IFNE    MIDI
  603.         clr.w    bytesinnotebuff-DB(a6)
  604.     ENDC
  605.         movea.l    mmd_songinfo(a2),a4
  606.         moveq    #0,d3
  607.         move.b    mmd_counter(a2),d3
  608.         addq.b    #1,d3
  609.         cmp.b    msng_tempo2(a4),d3
  610.         bge.s    plr_pnewnote    ;play new note
  611.         move.b    d3,mmd_counter(a2)
  612.         bne.w    nonewnote    ;do just fx
  613. ; --- new note!!
  614. plr_pnewnote:    clr.b    mmd_counter(a2)
  615.         tst.w    blkdelay-DB(a6)
  616.         beq.s    plr_noblkdelay
  617.         subq.w    #1,blkdelay-DB(a6)
  618.         bne.w    nonewnote
  619. ; --- now start to play it
  620. ; -------- GET ADDRESS OF NOTE DATA --------------------------------------
  621. plr_noblkdelay    move.w    mmd_pblock(a2),d0
  622.         bsr.w    GetNoteDataAddr
  623.         moveq    #0,d7        ;number of track
  624.         moveq    #0,d4
  625.         lea    trackdataptrs-DB(a6),a1
  626. ; -------- TRACK LOOP (FOR EACH TRACK) -----------------------------------
  627. plr_loop0:    movea.l    (a1)+,a5    ;get address of this track's struct
  628. ; ---------------- get the note numbers
  629.         moveq    #0,d3
  630.         move.b    (a3)+,d0    ;get the number of this note
  631.         bpl.s    plr_nothinote
  632.         moveq    #0,d0
  633. plr_nothinote    move.b    d0,trk_currnote(a5)
  634.         beq.s    plr_nosetprevn
  635.         move.b    d0,(a5)
  636. plr_nosetprevn    move.b    (a3),d3        ;instrument number
  637.         addq.l    #3,a3        ;adv. to next track
  638.         clr.b    trk_fxtype(a5)
  639. ; ---------------- check if there's an instrument number
  640.         and.w    #$3F,d3
  641.         beq.s    noinstnum
  642. ; ---------------- finally, save the number
  643.         subq.b    #1,d3
  644.         move.b    d3,trk_previnstr(a5) ;remember instr. number!
  645. ; ---------------- get the pointer of data's of this sample in Song-struct
  646.         move.w    d3,d0
  647.         asl.w    #3,d3
  648.         lea    0(a4,d3.w),a0    ;a0 contains now address of it
  649.         move.l    a0,trk_previnstra(a5)
  650. ; ---------------- get volume
  651.         move.b    inst_svol(a0),trk_prevvol(a5) ;vol of this instr
  652.         move.b    inst_strans(a0),trk_stransp(a5)
  653. ; ---------------- remember some values of this instrument
  654.         lea    holdvals-DB(a6),a0
  655.         adda.w    d0,a0
  656.     IFNE    HOLD
  657.         move.b    (a0),trk_inithold(a5)        ;hold
  658.         move.b    63(a0),trk_initdecay(a5)    ;decay
  659.     ENDC
  660.         move.b    2*63(a0),trk_finetune(a5)    ;finetune
  661.         move.b    6*63(a0),trk_outputdev(a5)    ;output dev
  662. ; ---------------- remember transpose
  663.         clr.w    trk_soffset(a5)        ;sample offset
  664.         clr.b    trk_miscflags(a5)    ;misc.
  665. noinstnum    addq.w    #1,d7
  666.         cmp.w    numtracks-DB(a6),d7
  667.         blt    plr_loop0
  668.         bsr.w    DoPreFXLoop
  669. ; -------- NOTE PLAYING LOOP ---------------------------------------------
  670.         moveq    #0,d7
  671.         lea    trackdataptrs-DB(a6),a1
  672. plr_loop2    movea.l    (a1)+,a5
  673.         tst.b    trk_fxtype(a5)
  674.         bne.s    plr_loop2_end
  675.         move.b    trk_currnote(a5),d1
  676.         beq.s    plr_loop2_end
  677. ; ---------------- play
  678.         move.l    a1,-(sp)
  679.         ext.w    d1
  680.         moveq    #0,d3
  681.         move.b    trk_previnstr(a5),d3    ;instr #
  682.         movea.l    trk_previnstra(a5),a3    ;instr data address
  683.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  684.         bne.s    plr_nohold0        ;not 0 -> OK
  685.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  686. ; ---------------- and finally:
  687. plr_nohold0    bsr    _PlayNote        ;play it
  688.         move.l    (sp)+,a1
  689. plr_loop2_end    addq.w    #1,d7
  690.         cmp.w    numtracks-DB(a6),d7
  691.         blt.s    plr_loop2
  692. ; -------- THE REST... ---------------------------------------------------
  693.         bsr.s    AdvSngPtr
  694. nonewnote    bsr.w    DoFX
  695. plr_endfx:
  696.     IFNE    MIDI
  697.         bsr    _StartDMA
  698.     ENDC
  699. plr_exit:    movem.l    (sp)+,d2-d7/a2-a6
  700.         rts
  701.  
  702. ; and advance song pointers
  703. AdvSngPtr    move.l    mmd_pblock(a2),fxplineblk-DB(a6) ;store pline/block for fx
  704.         move.w    nextblockline-DB(a6),d1
  705.         beq.s    plr_advlinenum
  706.         clr.w    nextblockline-DB(a6)
  707.         subq.w    #1,d1
  708.         bra.s    plr_linenumset
  709. plr_advlinenum    move.w    mmd_pline(a2),d1    ;get current line #
  710.         addq.w    #1,d1            ;advance line number
  711. plr_linenumset    cmp.w    numlines-DB(a6),d1     ;advance block?
  712.         bhi.s    plr_chgblock        ;yes.
  713.         tst.b    nextblock-DB(a6)    ;command F00/1Dxx?
  714.         beq.w    plr_nochgblock        ;no, don't change block
  715. ; -------- CHANGE BLOCK? -------------------------------------------------
  716. plr_chgblock    tst.b    nxtnoclrln-DB(a6)
  717.         bne.s    plr_noclrln
  718.         moveq    #0,d1            ;clear line number
  719. plr_noclrln    tst.w    mmd_pstate(a2)        ;play block or play song
  720.         bpl.w    plr_nonewseq        ;play block only...
  721. ; ********* BELOW CODE FOR MMD2 ONLY ************************************
  722. ; -------- CHANGE SEQUENCE -----------------------------------------------
  723. plr_skipseq    move.w    mmd_pseq(a2),d0        ;actually stored as << 2
  724.         movea.l    msng_pseqs(a4),a1    ;ptr to playseqs
  725.         movea.l    0(a1,d0.w),a0        ;a0 = ptr to curr PlaySeq
  726.         move.w    mmd_pseqnum(a2),d0    ;get play sequence number
  727.         tst.b    nextblock-DB(a6)
  728.         bmi.s    plr_noadvseq        ;Bxx sets nextblock to -1
  729.         addq.w    #1,d0            ;advance sequence number
  730. plr_noadvseq    cmp.w    40(a0),d0        ;is this the highest seq number??
  731.         blt.s    plr_notagain        ;no.
  732. ; -------- CHANGE SECTION ------------------------------------------------
  733.         move.w    mmd_psecnum(a2),d0    ;get section number
  734.         addq.w    #1,d0            ;increase..
  735.         cmp.w    msng_songlen(a4),d0    ;highest section?
  736.         blt.s    plr_nohisec
  737.         moveq    #0,d0            ;yes.
  738. plr_nohisec    move.w    d0,mmd_psecnum(a2)    ;push back.
  739.         add.w    d0,d0
  740.         movea.l    msng_sections(a4),a0    ;section table
  741.         move.w    0(a0,d0.w),d0        ;new playseqlist number
  742.         add.w    d0,d0
  743.         add.w    d0,d0
  744.         move.w    d0,mmd_pseq(a2)
  745.         movea.l    0(a1,d0.w),a0        ;a0 = ptr to new PlaySeq
  746.         moveq    #0,d0            ;playseq OFFSET = 0
  747. ; -------- FETCH BLOCK NUMBER FROM SEQUENCE ------------------------------
  748. plr_notagain    move.w    d0,mmd_pseqnum(a2)    ;remember new playseq pos
  749.         add.w    d0,d0
  750.         move.w    42(a0,d0.w),d0        ;get number of the block
  751.         bmi.s    plr_skipseq    ;neg. values for future expansion
  752. plr_changeblk
  753.     IFNE    CHECK
  754.         cmp.w    msng_numblocks(a4),d0    ;beyond last block??
  755.         blt.s    plr_nolstblk        ;no..
  756.         moveq    #0,d0            ;play block 0
  757.     ENDC
  758. plr_nolstblk    move.w    d0,mmd_pblock(a2)    ;store block number
  759. plr_nonewseq    clr.w    nextblock-DB(a6)     ;clear this if F00 set it
  760. ; ------------------------------------------------------------------------
  761. plr_nochgblock    move.w    d1,mmd_pline(a2)    ;set new line number
  762.  
  763.     IFNE    HOLD
  764.         lea    trackdataptrs-DB(a6),a5
  765.         move.w    mmd_pblock(a2),d0    ;pblock
  766.         bsr.w    GetBlockAddr
  767.         move.w    mmd_pline(a2),d0    ;play line
  768.         move.b    msng_tempo2(a4),d3    ;interrupts/note
  769.         move.w    (a0),d7        ;# of tracks
  770.         add.w    d0,d0
  771.         add.w    d0,d0        ;d0 = d0 * 4
  772.         mulu    d7,d0
  773.         lea    8(a0,d0.l),a3
  774.         subq.b    #1,d7
  775. plr_chkhold    movea.l    (a5)+,a1        ;track data
  776.         tst.b    trk_noteoffcnt(a1)    ;hold??
  777.         bmi.s    plr_holdend        ;no.
  778.         move.b    (a3),d1            ;get the 1st byte..
  779.         bne.s    plr_hold1
  780.         move.b    1(a3),d0
  781.         and.b    #$3F,d0
  782.         beq.s    plr_holdend        ;don't hold
  783.         bra.s    plr_hold2
  784. plr_hold1    and.b    #$7f,d1            ;note??
  785.         beq.s    plr_hold2        ;no, cont hold..
  786.         move.b    2(a3),d1
  787.         subq.b    #3,d1            ;is there command 3 (slide)
  788.         bne.s    plr_holdend        ;no -> end holding
  789. plr_hold2    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  790. plr_holdend    addq.l    #4,a3        ;next note
  791.         dbf    d7,plr_chkhold
  792.     ENDC
  793.         rts
  794.  
  795. ; *******************************************************************
  796. ; DoPreFXLoop:    Loop and call DoPreFX
  797. ; *******************************************************************
  798. DoPreFXLoop:
  799. ; -------- PRE-FX COMMAND HANDLING LOOP ----------------------------------
  800.         moveq    #0,d5    ;command page count
  801. plr_loop1    move.w    mmd_pblock(a2),d0
  802.         bsr.w    GetBlockAddr
  803.         move.w    d5,d1
  804.         move.w    mmd_pline(a2),d2
  805.         bsr.w    GetCmdPointer
  806.         movea.l    a0,a3
  807.         moveq    #0,d7    ;clear track count
  808.         lea    trackdataptrs-DB(a6),a1
  809. plr_loop1_1    movea.l    (a1)+,a5
  810.         move.b    (a3),d0            ;command #
  811.         beq.s    plr_loop1_end
  812.         moveq    #0,d4
  813.         move.b    1(a3),d4        ;data byte
  814.         and.w    #$3F,d0
  815.         bsr.s    DoPreFX
  816.         or.b    d0,trk_fxtype(a5)
  817. plr_loop1_end    adda.w    d6,a3            ;next track...
  818.         addq.w    #1,d7
  819.         cmp.w    numtracks-DB(a6),d7
  820.         blt.s    plr_loop1_1
  821.         addq.w    #1,d5
  822.         cmp.w    numpages-DB(a6),d5
  823.         bls.s    plr_loop1
  824.         rts
  825.  
  826. ; *******************************************************************
  827. ; DoPreFX: Perform effects that must be handled before note playing
  828. ; *******************************************************************
  829. ; args:        a6 = DB            d0 = command number (w)
  830. ;        a5 = track data        d5 = note number
  831. ;        a4 = song        d4 = data
  832. ;                    d7 = track #
  833. ; returns:    d0 = 0: play - d0 = 1: don't play
  834.  
  835. rtplay        MACRO
  836.         moveq    #0,d0
  837.         rts
  838.         ENDM
  839. rtnoplay    MACRO
  840.         moveq    #1,d0
  841.         rts
  842.         ENDM
  843.  
  844. DoPreFX:    add.b    d0,d0    ;* 2
  845.         move.w    f_table(pc,d0.w),d0
  846.         jmp    fst(pc,d0.w)
  847. fst
  848. f_table        dc.w    fx-fst,fx-fst,fx-fst,f_03-fst,fx-fst,fx-fst,fx-fst,fx-fst
  849.         dc.w    f_08-fst,f_09-fst,fx-fst,f_0b-fst,f_0c-fst,fx-fst,f_0e-fst,f_0f-fst
  850.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_15-fst,f_16-fst,fx-fst
  851.         dc.w    fx-fst,f_19-fst,fx-fst,fx-fst,f_1c-fst,f_1d-fst,f_1e-fst,f_1f-fst
  852.         dc.w    f_20-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
  853.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_2e-fst,f_2f-fst
  854.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
  855.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,fx-fst
  856. ; ---------------- tempo (F)
  857. f_0f        tst.b    d4        ;test effect qual..
  858.         beq    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  859.         cmp.b    #$f0,d4        ;..is zero, go to next block
  860.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  861. ; ---------------- just an ordinary "change tempo"-request
  862.         moveq    #0,d0        ;will happen!!!
  863.         move.b    d4,d0
  864.         bsr    _SetTempo    ;change The Tempo
  865. fx        rtplay
  866. ; ---------------- no, it was FFx, something special will happen!!
  867. fx0fspecial:    cmp.b    #$f2,d4
  868.         beq.s    f_1f
  869.         cmp.b    #$f4,d4
  870.         beq.s    f_1f
  871.         cmp.b    #$f5,d4
  872.         bne.s    isfxfe
  873. ; ---------------- FF2 (or 1Fxx)
  874. f_1f
  875.     IFNE    HOLD
  876.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  877.         bne.s    f_1frts            ;not 0 -> OK
  878.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  879.     ENDC
  880. f_1frts        rtnoplay
  881. isfxfe:        cmp.b    #$fe,d4
  882.         bne.s    notcmdfe
  883. ; ---------------- it was FFE, stop playing
  884.         clr.w    mmd_pstate(a2)
  885.         bsr.w    SoundOff
  886.         adda.w    #8,sp    ;2 subroutine levels
  887.         bra.w    plr_exit
  888. f_ffe_no8    rtplay
  889. notcmdfe:    cmp.b    #$fd,d4 ;change period
  890.         bne.s    isfxff
  891. ; ---------------- FFD, change the period, don't replay the note
  892.     IFNE    CHECK
  893.         cmp.w    maxaudiotrk-DB(a6),d7 ;no tracks above 4, thank you!!
  894.         bge.s    f_0f_rts
  895.     ENDC
  896.         move.l    trk_periodtbl(a5),d1    ;period table
  897.         beq.s    f_1frts
  898.         movea.l    d1,a0
  899.         move.b    trk_currnote(a5),d0
  900.         subq.b    #1,d0    ;sub 1 to make "real" note number
  901.     IFNE    CHECK
  902.         bmi.s    f_1frts
  903.     ENDC
  904.         add.b    msng_playtransp(a4),d0
  905.         add.b    trk_stransp(a5),d0
  906.         add.w    d0,d0
  907.         bmi.s    f_1frts
  908.         move.w    0(a0,d0.w),trk_prevper(a5) ;get & push the period
  909.         rtnoplay
  910. isfxff        cmp.b    #$ff,d4        ;note off??
  911.         bne.s    isfxf7
  912.         move.w    d7,d0
  913.         move.l    a1,-(sp)
  914.         bsr.w    _ChannelOff
  915.         move.l    (sp)+,a1
  916.         rtplay
  917. isfxf7
  918.     IFNE    MIDI
  919.         cmp.b    #$f7,d4        ;wait SysX
  920.         bne.s    f_0f_rts
  921.         tst.b    sysx-DB(a6)
  922.         beq.s    f_0f_rts
  923.         move.w    #2,blkdelay-DB(a6)
  924.     ENDC
  925. f_0f_rts    rtplay
  926. ; ---------------- F00, called Pattern Break in ST
  927. fx0fchgblck:    move.b    #1,nextblock-DB(a6) ;next block????...YES!!!! (F00)
  928.         bra.s    f_0f_rts
  929. ; ---------------- was not Fxx, then it's something else!!
  930. f_0e
  931.     IFNE    CHECK
  932.         cmp.b    maxaudiotrk-DB(a6),d7
  933.         bge.s    f_0e_rts
  934.     ENDC
  935.         bset    #0,trk_miscflags(a5)
  936.         move.b    d4,trk_wfcmd+1(a5) ;set waveform command position ptr
  937. f_0e_rts    rtplay
  938. ; ---------------- change volume
  939. f_0c        move.b    d4,d0
  940.         bpl.s    plr_nosetdefvol
  941.         and.b    #$7F,d0
  942.     IFNE    CHECK
  943.         cmp.b    #64,d0
  944.         bgt.s    go_nocmd
  945.     ENDC
  946.         moveq    #0,d1
  947.         move.b    trk_previnstr(a5),d1
  948.         asl.w    #3,d1
  949.         move.b    d0,inst_svol(a4,d1.w)    ;set new svol
  950.         bra.s    plr_setvol
  951. plr_nosetdefvol    btst    #4,msng_flags(a4)    ;look at flags
  952.         bne.s    volhex
  953.         lsr.b    #4,d0        ;get number from left
  954.         mulu    #10,d0        ;number of tens
  955.         move.b    d4,d1        ;get again
  956.         and.b    #$0f,d1        ;this time don't get tens
  957.         add.b    d1,d0        ;add them
  958. volhex:
  959.     IFNE    CHECK
  960.         cmp.b    #64,d0
  961.         bhi.s    go_nocmd
  962.     ENDC
  963. plr_setvol    move.b    d0,trk_prevvol(a5)
  964. go_nocmd    rtplay
  965. ; ---------------- tempo2 change??
  966. f_09
  967.     IFNE    CHECK
  968.         and.b    #$1F,d4
  969.         bne.s    fx9chk
  970.         moveq    #$20,d4
  971.     ENDC
  972. fx9chk:        move.b    d4,msng_tempo2(a4)
  973. f_09_rts    rtplay
  974. ; ---------------- block delay
  975. f_1e        tst.w    blkdelay-DB(a6)
  976.         bne.s    f_1e_rts
  977.         addq.w    #1,d4
  978.         move.w    d4,blkdelay-DB(a6)
  979. f_1e_rts    rtplay
  980. ; ---------------- finetune
  981. f_15
  982.     IFNE    CHECK
  983.         cmp.b    #7,d4
  984.         bgt.s    f_15_rts
  985.         cmp.b    #-8,d4
  986.         blt.s    f_15_rts
  987.     ENDC
  988.         move.b    d4,trk_finetune(a5)
  989. f_15_rts    rtplay
  990. ; ---------------- repeat loop
  991. f_16        tst.b    d4
  992.         bne.s    plr_dorpt
  993.         move.w    mmd_pline(a2),rptline-DB(a6)
  994.         bra.s    f_16_rts
  995. plr_dorpt    tst.w    rptcounter-DB(a6)
  996.         beq.s    plr_newrpt
  997.         subq.w    #1,rptcounter-DB(a6)
  998.         beq.s    f_16_rts
  999.         bra.s    plr_setrptline
  1000. plr_newrpt    move.b    d4,rptcounter+1-DB(a6)
  1001. plr_setrptline    move.w    rptline-DB(a6),d0
  1002.         addq.w    #1,d0
  1003.         move.w    d0,nextblockline-DB(a6)
  1004. f_16_rts    rtplay
  1005. ; ---------------- preset change
  1006. f_1c
  1007.     IFNE    MIDI
  1008.         cmp.b    #$80,d4
  1009.         bhi.s    f_1c_rts
  1010.         moveq    #0,d1
  1011.         move.b    trk_previnstr(a5),d1
  1012.         add.w    d1,d1
  1013.         lea    ext_midipsets-DB(a6),a0
  1014.         ext.w    d4
  1015.         move.w    d4,0(a0,d1.w)        ;set MIDI preset
  1016.     ENDC
  1017. f_1c_rts    rtplay
  1018. ; ---------------- note off time set??
  1019. f_08
  1020.     IFNE    HOLD
  1021.     IFNE    MIDI
  1022.         move.l    trk_previnstra(a5),d0
  1023.         beq.s    1$
  1024.         move.l    d0,a0
  1025.         tst.b    inst_midich(a0)
  1026.         bne.s    2$ ;two-digit hold for MIDI instrs
  1027.     ENDC
  1028. 1$        move.b    d4,d0
  1029.         lsr.b    #4,d0        ;extract left  nibble
  1030.         and.b    #$0f,d4        ; "   "  right  "  "
  1031.         move.b    d0,trk_initdecay(a5)    ;left = decay
  1032. 2$        move.b    d4,trk_inithold(a5)    ;right = hold
  1033.     ENDC
  1034.         rtplay
  1035. ; ---------------- sample begin offset
  1036. f_19        lsl.w    #8,d4
  1037.         move.w    d4,trk_soffset(a5)
  1038. f_19_rts    rtplay
  1039. ; ---------------- cmd Bxx, "position jump"
  1040. f_0b
  1041.     IFNE    CHECK
  1042. chk0b_mmd2    move.w    mmd_pseq(a2),d0        ;get seq number
  1043.         movea.l    msng_pseqs(a4),a0    ;ptr to playseqs
  1044.         movea.l    0(a0,d0.w),a0        ;a0 = ptr to curr PlaySeq
  1045.         cmp.w    40(a0),d4        ;test song length
  1046.         bhi.s    f_0b_rts
  1047. chk0b_end
  1048.     ENDC
  1049.         move.w    d4,mmd_pseqnum(a2)
  1050.         st    nextblock-DB(a6)    ; = 1
  1051. f_0b_rts    rtplay
  1052. ; ---------------- cmd 1Dxx, jump to next seq, line # specified
  1053. f_1d        move.w    #$1ff,nextblock-DB(a6)
  1054.         addq.w    #1,d4
  1055.         move.w    d4,nextblockline-DB(a6)
  1056.         rtplay
  1057. ; ---------------- try portamento (3)
  1058. f_03
  1059.     IFNE    CHECK
  1060.         cmp.w    maxaudiotrk-DB(a6),d7
  1061.         bge.s    f_03_rts
  1062.     ENDC
  1063.         moveq    #0,d0
  1064.         move.b    trk_currnote(a5),d0
  1065.         subq.b    #1,d0        ;subtract note number
  1066.         bmi.s    plr_setfx3spd    ;0 -> set new speed
  1067.         move.l    trk_periodtbl(a5),d1
  1068.         beq.s    f_03_rts
  1069.         movea.l    d1,a0
  1070.         add.b    msng_playtransp(a4),d0    ;play transpose
  1071.         add.b    trk_stransp(a5),d0 ;and instrument transpose
  1072.         bmi.s    f_03_rts    ;again.. too low
  1073.         add.w    d0,d0
  1074.         move.w    0(a0,d0.w),trk_porttrgper(a5) ;period of this note is the target
  1075. plr_setfx3spd:    tst.b    d4        ;qual??
  1076.         beq.s    f_03_rts    ;0 -> do nothing
  1077.         move.b    d4,trk_prevportspd(a5)    ;store speed
  1078. f_03_rts    rtnoplay
  1079.  
  1080. ; ---------------- command 20 (backwards)
  1081. f_20        tst.b    d4
  1082.         bne.s    1$
  1083.         bset    #6,trk_miscflags(a5)    ;play backwards
  1084. 1$        rtplay
  1085. ; ---------------- command 2E (panpot)
  1086.         XREF    Mix_FX2E
  1087. f_2e        jsr    Mix_FX2E(pc)
  1088.         rtplay
  1089. ; ---------------- command 2F (fx settings)
  1090.         XREF    Mix_FX2F
  1091. f_2f        jsr    Mix_FX2F(pc)
  1092.         rtplay
  1093.  
  1094. ; *******************************************************************
  1095. ; DoFX: Handle effects, hold/fade etc.
  1096. ; *******************************************************************
  1097. DoFX        moveq    #0,d3
  1098.         move.b    mmd_counter(a2),d3
  1099.     IFNE    HOLD
  1100.         lea    trackdataptrs-DB(a6),a1
  1101. ; Loop 1: Hold/Fade handling
  1102.         moveq    #0,d7    ;clear track count
  1103. dofx_loop1    movea.l    (a1)+,a5
  1104.         bsr.w    HoldAndFade
  1105.         addq.w    #1,d7
  1106.         cmp.w    numtracks-DB(a6),d7
  1107.         blt.s    dofx_loop1
  1108.     ENDC
  1109. ; Loop 2: Track command handling
  1110.         moveq    #0,d5    ;command page count
  1111. dofx_loop2    move.w    fxplineblk-DB(a6),d0
  1112.         bsr.w    GetBlockAddr
  1113.         movea.l    a0,a3
  1114.         bsr.w    StoreBlockDims
  1115. dofx_sbd_mmd0    move.w    d5,d1
  1116.         move.w    fxplineblk+2-DB(a6),d2
  1117.         movea.l    a3,a0
  1118.         bsr.s    GetCmdPointer
  1119.         movea.l    a0,a3
  1120.         moveq    #0,d7    ;clear track count
  1121.         lea    trackdataptrs-DB(a6),a1
  1122. dofx_loop2_1    movea.l    (a1)+,a5
  1123.         moveq    #0,d4
  1124.         move.b    (a3),d0            ;command #
  1125.         move.b    1(a3),d4        ;data byte
  1126.         and.w    #$1F,d0
  1127. dofx_mmd0maskd    tst.b    trk_fxtype(a5)
  1128.         bgt.s    dofx_lend2_1    ;1 = skip
  1129.     IFNE    MIDI
  1130.         beq.s    dofx_chfx
  1131.         bsr.w    MIDIFX
  1132.         bra.s    dofx_lend2_1
  1133.     ENDC
  1134.     IFEQ    MIDI
  1135.         bne.s    dofx_lend2_1
  1136.     ENDC
  1137. dofx_chfx    bsr.w    ChannelFX
  1138. dofx_lend2_1    adda.w    d6,a3            ;next track...
  1139.         addq.w    #1,d7
  1140.         cmp.w    numtracks-DB(a6),d7
  1141.         blt.s    dofx_loop2_1
  1142.         addq.w    #1,d5
  1143.         cmp.w    numpages-DB(a6),d5
  1144.         bls.s    dofx_loop2
  1145. ; Loop 3: Updating audio hardware
  1146.         moveq    #0,d7    ;clear track count
  1147.         lea    trackdataptrs-DB(a6),a1
  1148. dofx_loop3    movea.l    (a1)+,a5
  1149.     IFNE    HOLD
  1150.         tst.b    trk_fxtype(a5)
  1151.         bne.s    dofx_lend3    ;only in case 0 (norm)
  1152.     ENDC
  1153.     IFEQ    HOLD
  1154.         cmp.w    maxaudiotrk-DB(a6),d7
  1155.         bge.s    dofx_stopl3
  1156.     ENDC
  1157.         bsr.w    UpdatePerVol
  1158. dofx_lend3    addq.w    #1,d7
  1159.         cmp.w    numtracks-DB(a6),d7
  1160.         blt.s    dofx_loop3
  1161. dofx_stopl3    rts
  1162.  
  1163. ; *******************************************************************
  1164. ; GetCmdPointer: Return command pointer for track 0
  1165. ; *******************************************************************
  1166. ; args:        a0 = block pointer
  1167. ;        d1 = page number
  1168. ;        d2 = line number
  1169. ;        a2 = module
  1170. ; result:    a0 = command pointer (i.e. trk 0 note + 2)
  1171. ;        d6 = track advance (bytes)
  1172. ; scratches:    d0, d1, d2, a0
  1173. ; Note: no num_pages check! If numpages > 0 it can be assumed that
  1174. ; extra pages exist.
  1175.  
  1176. GetCmdPointer
  1177.         mulu    (a0),d2        ;d2 = line # * numtracks
  1178.         add.l    d2,d2        ;d2 *= 2...
  1179.         subq.w    #1,d1
  1180.         bmi.s    gcp_page0
  1181.         movea.l    4(a0),a0
  1182.         movea.l    12(a0),a0
  1183.         add.w    d1,d1
  1184.         add.w    d1,d1
  1185.         movea.l    4(a0,d1.w),a0    ;command data
  1186.         adda.l    d2,a0
  1187.         moveq    #2,d6
  1188.         rts
  1189. gcp_page0    add.l    d2,d2        ;d2 *= 4
  1190.         lea    10(a0,d2.l),a0    ;offs: 4 = header, 2 = note
  1191.         moveq    #4,d6        ;track advance (bytes)
  1192.         rts
  1193.  
  1194. ; *******************************************************************
  1195. ; GetBlockAddr: Return pointer to block
  1196. ; *******************************************************************
  1197. ; args:        d0 = block number
  1198. ; result:    a0 = block pointer
  1199. ; scratches: d0, a0
  1200.  
  1201. GetBlockAddr    movea.l    mmd_blockarr(a2),a0
  1202.         add.w    d0,d0
  1203.         add.w    d0,d0
  1204.         movea.l    0(a0,d0.w),a0
  1205.         rts
  1206.  
  1207. ; *******************************************************************
  1208. ; GetNoteDataAddr: Check & return addr. of current note
  1209. ; *******************************************************************
  1210. ;args:        d0 = pblock        a6 = DB
  1211. ;returns:    a3 = address
  1212. ;scratches:    d0, a0, d1
  1213.  
  1214. GetNoteDataAddr    bsr.w    GetBlockAddr
  1215.         movea.l    a0,a3
  1216.         bsr.w    StoreBlockDims
  1217.         move.w    numlines-DB(a6),d1
  1218.         move.w    mmd_pline(a2),d0
  1219.         cmp.w    d1,d0        ;check if block end exceeded...
  1220.         bls.s    plr_nolinex
  1221.         move.w    d1,d0
  1222. plr_nolinex    add.w    d0,d0
  1223.         add.w    d0,d0    ;d0 = d0 * 4
  1224.         mulu    numtracks-DB(a6),d0
  1225.         lea    8(a3,d0.l),a3    ;address of current note
  1226.         rts
  1227.  
  1228. ; *******************************************************************
  1229. ; StoreBlockDims: Store block dimensions
  1230. ; *******************************************************************
  1231. ; args:        a0 = block ptr, a6 = DB
  1232.  
  1233. StoreBlockDims    move.l    (a0)+,numtracks-DB(a6)    ;numtracks & lines
  1234.         tst.l    (a0)            :BlockInfo
  1235.         beq.s    sbd_1page
  1236.         movea.l    (a0),a0
  1237.         move.l    12(a0),d0        ;BlockInfo.pagetable
  1238.         beq.s    sbd_1page
  1239.         movea.l    d0,a0
  1240.         move.w    (a0),numpages-DB(a6)    ;num_pages
  1241.         rts
  1242. sbd_1page    clr.w    numpages-DB(a6)
  1243.         rts
  1244.  
  1245. ; *******************************************************************
  1246. ; HoldAndFade: Handle hold/fade
  1247. ; *******************************************************************
  1248. ; args:        a5 = track data
  1249. ;        a6 = DB
  1250. ;        d7 = track #
  1251. ; scratches:    d0, d1, a0
  1252.  
  1253.     IFNE    HOLD
  1254. HoldAndFade
  1255.     IFNE    MIDI
  1256.         tst.b    trk_prevmidin(a5)    ;is it MIDI??
  1257.         bne.w    plr_haf_midi
  1258.     ENDC
  1259.     IFNE    CHECK
  1260.         cmp.w    maxaudiotrk-DB(a6),d7
  1261.         bge.w    plr_haf_midi    ;no non-MIDI effects in tracks 4 - 15
  1262.     ENDC
  1263.         tst.b    trk_noteoffcnt(a5)
  1264.         bmi.s    plr_haf_noholdexp
  1265.         subq.b    #1,trk_noteoffcnt(a5)
  1266.         bpl.s    plr_haf_noholdexp
  1267.     IFNE    SYNTH
  1268.         tst.b    trk_synthtype(a5)        ;synth/hybrid??
  1269.         beq.s    plr_nosyndec
  1270.         move.b    trk_decay(a5),trk_volcmd+1(a5)    ;set volume command pointer
  1271.         clr.b    trk_volwait(a5)            ;abort WAI
  1272.         bra.s    plr_haf_noholdexp
  1273.     ENDC
  1274. plr_nosyndec    move.b    trk_decay(a5),trk_fadespd(a5)    ;set fade...
  1275.         bne.s    plr_haf_noholdexp        ;if > 0, don't stop sound
  1276.         move.w    d7,d0
  1277.         move.l    a1,-(sp)
  1278.         bsr.w    _ChannelOff
  1279.         movea.l    (sp)+,a1
  1280. plr_haf_noholdexp
  1281.         move.b    trk_fadespd(a5),d0    ;fade??
  1282.         beq.s    plr_haf_dofx        ;no.
  1283.         sub.b    d0,trk_prevvol(a5)
  1284.         bpl.s    plr_nofade2low
  1285.         clr.b    trk_prevvol(a5)
  1286.         clr.b    trk_fadespd(a5)        ;fade no more
  1287. plr_nofade2low
  1288. plr_haf_dofx    clr.b    trk_fxtype(a5)
  1289. plr_haf_rts    rts
  1290. ; MIDI version
  1291. plr_haf_midi
  1292.         st    trk_fxtype(a5)
  1293.     IFNE    MIDI
  1294.         tst.b    trk_noteoffcnt(a5)
  1295.         bmi.s    plr_haf_rts
  1296.         subq.b    #1,trk_noteoffcnt(a5)
  1297.         bpl.s    plr_haf_rts
  1298.         move.b    trk_prevmidin(a5),d1
  1299.         beq.s    plr_haf_rts
  1300.         lea    noteondata-DB(a6),a0
  1301.         exg.l    a5,a1
  1302.         bsr.w    choff_midi
  1303.         exg.l    a5,a1
  1304.     ENDC
  1305.         rts
  1306. ;hold
  1307.     ENDC
  1308.  
  1309. ; *******************************************************************
  1310. ; ChannelFX:    Do an effect on a channel
  1311. ; *******************************************************************
  1312. ;args:                    d3 = counter
  1313. ;        a4 = song struct    d4 = command qual (long, byte used)
  1314. ;        a5 = track data ptr    
  1315. ;        a6 = DB            d0 = command (long, byte used)
  1316. ;                    d7 = track (channel) number
  1317. ;scratches: d0, d1, d4, a0
  1318.  
  1319. ChannelFX    add.b    d0,d0    ;* 2
  1320.         move.w    fx_table(pc,d0.w),d0
  1321.         jmp    fxs(pc,d0.w)
  1322. fxs:
  1323. fx_table    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1324.         dc.w    fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
  1325.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_0c-fxs,fx_0d-fxs,fx_xx-fxs
  1326.         dc.w    fx_0f-fxs
  1327.         dc.w    fx_10-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
  1328.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
  1329.         dc.w    fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1330.         dc.w    fx_1f-fxs
  1331.         dc.w    fx_20-fxs,fx_21-fxs,fx_22-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1332.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1333.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1334.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1335. ;    **************************************** Effect 01 & 02 *
  1336. fx_02        neg.w    d4
  1337. fx_01        tst.b    d3
  1338.         bne.s    fx_01nocnt0
  1339.         btst    #5,msng_flags(a4)    ;FLAG_STSLIDE??
  1340.         bne.s    fx_xx
  1341. fx_01nocnt0    move.l    #AUDIO_CONST,d1
  1342.         move.l    d1,d0
  1343.         tst.w    trk_prevper(a5)
  1344.         beq.s    1$
  1345.         divu    trk_prevper(a5),d0
  1346.         sub.w    d4,d0
  1347.         beq.s    1$
  1348.         divu    d0,d1
  1349.         move.w    d1,trk_prevper(a5)
  1350. 1$        ;fx_xx is just a RTS
  1351. fx_xx        rts
  1352. ;    **************************************** Effect 11 ******
  1353. fx_11        tst.b    d3
  1354.         beq.s    fx_01nocnt0
  1355. fx_11rts    rts
  1356. ;    **************************************** Effect 12 ******
  1357. fx_12        neg.w    d4
  1358.         tst.b    d3
  1359.         beq.s    fx_01nocnt0
  1360. fx_12rts    rts
  1361. ;    **************************************** Effect 21 ******
  1362. fx_21        move.w    trk_prevper(a5),d0
  1363.         move.w    d0,d1
  1364.         mulu    d4,d0
  1365.         lsl.l    #5,d0
  1366.         swap    d0
  1367.         add.w    d0,d1
  1368.         bcc.s    1$
  1369.         moveq    #-1,d1    ;max. freq = 65535 Hz
  1370. 1$        move.w    d1,trk_prevper(a5)
  1371.         rts
  1372. ;    **************************************** Effect 22 ******
  1373. fx_22        move.w    trk_prevper(a5),d0
  1374.         move.w    d0,d1
  1375.         mulu    d4,d0
  1376.         lsl.l    #5,d0
  1377.         swap    d0
  1378.         sub.w    d0,d1
  1379.         bcc.s    1$
  1380.         moveq    #1,d1
  1381. 1$        move.w    d1,trk_prevper(a5)
  1382.         rts
  1383. ;    **************************************** Effect 00 ******
  1384. fx_00        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio
  1385.         beq.s    fx_00rts
  1386.         move.l    d3,d0
  1387.         divu    #3,d0
  1388.         swap    d0
  1389.         subq.b    #1,d0
  1390.         bgt.s    fx_arp2
  1391.         blt.s    fx_arp0
  1392.         and.b    #$0f,d4
  1393.         bra.s    fx_doarp
  1394. fx_arp0        lsr.b    #4,d4
  1395.         bra.s    fx_doarp
  1396. fx_arp2        moveq    #0,d4
  1397. fx_doarp:    move.b    (a5),d0
  1398.         subq.b    #1,d0        ;-1 to make it 0 - 127
  1399.         add.b    msng_playtransp(a4),d0    ;add play transpose
  1400.         add.b    trk_stransp(a5),d0    ;add instrument transpose
  1401.         add.b    d0,d4
  1402.         move.l    trk_periodtbl(a5),d1
  1403.         beq.s    fx_00rts
  1404.         movea.l    d1,a0
  1405.         add.b    d0,d0
  1406.         move.w    0(a0,d0.w),d0    ;base note period
  1407.         add.b    d4,d4
  1408.         sub.w    0(a0,d4.w),d0    ;calc difference from base note
  1409.         move.w    d0,trk_arpadjust(a5)
  1410. fx_00rts    rts
  1411. ;    **************************************** Effect 04 ******
  1412. fx_14        move.b    #6,trk_vibshift(a5)
  1413.         bra.s    vib_cont
  1414. fx_04        move.b    #5,trk_vibshift(a5)
  1415. vib_cont    tst.b    d3
  1416.         bne.s    nonvib
  1417.         move.b    d4,d1
  1418.         beq.s    nonvib
  1419.         and.w    #$0f,d1
  1420.         beq.s    plr_chgvibspd
  1421.         move.w    d1,trk_vibrsz(a5)
  1422. plr_chgvibspd    and.b    #$f0,d4
  1423.         beq.s    nonvib
  1424.         lsr.b    #3,d4
  1425.         and.b    #$3e,d4
  1426.         move.b    d4,trk_vibrspd(a5)
  1427. nonvib        move.b    trk_vibroffs(a5),d0
  1428.         lsr.b    #2,d0
  1429.         and.w    #$1f,d0
  1430.         moveq    #0,d1
  1431.         lea    sinetable(pc),a0
  1432.         move.b    0(a0,d0.w),d0
  1433.         ext.w    d0
  1434.         muls    trk_vibrsz(a5),d0
  1435.         move.b    trk_vibshift(a5),d1
  1436.         asr.w    d1,d0
  1437.         move.b    trk_vibrspd(a5),d1
  1438.         add.b    d1,trk_vibroffs(a5)
  1439.         move.l    #AUDIO_CONST,d1
  1440.         move.l    d1,d4
  1441.         tst.w    trk_prevper(a5)
  1442.         beq.s    1$
  1443.         divu    trk_prevper(a5),d4
  1444.         add.w    d0,d4
  1445.         beq.s    1$
  1446.         divu    d4,d1
  1447.         sub.w    trk_prevper(a5),d1
  1448.         move.w    d1,trk_vibradjust(a5)
  1449. 1$
  1450. fx_04rts    rts
  1451. ;    **************************************** Effect 06 ******
  1452. fx_06:        tst.b    d3
  1453.         bne.s    fx_06nocnt0
  1454.         btst    #5,msng_flags(a4)
  1455.         bne.s    fx_04rts
  1456. fx_06nocnt0    bsr.s    plr_volslide        ;Volume slide
  1457.         bra.s    nonvib            ;+ Vibrato
  1458. ;    **************************************** Effect 07 ******
  1459. fx_07        tst.b    d3
  1460.         bne.s    nontre
  1461.         move.b    d4,d1
  1462.         beq.s    nontre
  1463.         and.w    #$0f,d1
  1464.         beq.s    plr_chgtrespd
  1465.         move.w    d1,trk_tremsz(a5)
  1466. plr_chgtrespd    and.b    #$f0,d4
  1467.         beq.s    nontre
  1468.         lsr.b    #2,d4
  1469.         and.b    #$3e,d4
  1470.         move.b    d4,trk_tremspd(a5)
  1471. nontre        move.b    trk_tremoffs(a5),d0
  1472.         lsr.b    #3,d0
  1473.         and.w    #$1f,d0
  1474.         lea    sinetable(pc),a0
  1475.         move.b    0(a0,d0.w),d1
  1476.         ext.w    d1
  1477.         muls    trk_tremsz(a5),d1
  1478.         asr.w    #7,d1
  1479.         move.b    trk_tremspd(a5),d0
  1480.         add.b    d0,trk_tremoffs(a5)
  1481.         add.b    trk_prevvol(a5),d1
  1482.         bpl.s    tre_pos
  1483.         moveq    #0,d1
  1484. tre_pos        cmp.b    #64,d1
  1485.         ble.s    tre_no2hi
  1486.         moveq    #64,d1
  1487. tre_no2hi    move.b    d1,trk_tempvol(a5)
  1488.         rts
  1489. ;    ********* VOLUME SLIDE FUNCTION *************************
  1490. plr_volslide    move.b    d4,d0
  1491.         moveq    #0,d1
  1492.         move.b    trk_prevvol(a5),d1 ;move previous vol to d1
  1493.         and.b    #$f0,d0
  1494.         bne.s    crescendo
  1495.         sub.b    d4,d1    ;sub from prev. vol
  1496. voltest0    bpl.s    novolover64
  1497.         moveq    #0,d1    ;volumes under zero not accepted
  1498.         bra.s    novolover64
  1499. crescendo:    lsr.b    #4,d0
  1500.         add.b    d0,d1
  1501. voltest        cmp.b    #64,d1
  1502.         ble.s    novolover64
  1503.         moveq    #64,d1
  1504. novolover64    move.b    d1,trk_prevvol(a5)
  1505. volsl_rts    rts
  1506. ;    **************************************** Effect 0D/0A ***
  1507. fx_0a:
  1508. fx_0d:        tst.b    d3
  1509.         bne.s    plr_volslide
  1510.         btst    #5,msng_flags(a4)
  1511.         beq.s    plr_volslide
  1512.         rts
  1513. ;    **************************************** Effect 05 ******
  1514. fx_05:        tst.b    d3
  1515.         bne.s    fx_05nocnt0
  1516.         btst    #5,msng_flags(a4)
  1517.         bne.s    fx_05rts
  1518. fx_05nocnt0    bsr.s    plr_volslide
  1519.         bra.s    fx_03nocnt0
  1520. fx_05rts    rts
  1521. ;    **************************************** Effect 1A ******
  1522. fx_1a        tst.b    d3
  1523.         bne.s    volsl_rts
  1524.         move.b    trk_prevvol(a5),d1
  1525.         add.b    d4,d1
  1526.         bra.s    voltest
  1527. ;    **************************************** Effect 1B ******
  1528. fx_1b        tst.b    d3
  1529.         bne.s    volsl_rts
  1530.         move.b    trk_prevvol(a5),d1
  1531.         sub.b    d4,d1
  1532.         bra.s    voltest0
  1533. ;    **************************************** Effect 03 ******
  1534. fx_03:        tst.b    d3
  1535.         bne.s    fx_03nocnt0
  1536.         btst    #5,msng_flags(a4)
  1537.         bne.s    fx_03rts
  1538. fx_03nocnt0    move.w    trk_porttrgper(a5),d0    ;d0 = target period
  1539.         beq.s    fx_03rts
  1540.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  1541.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  1542.         cmp.w    d0,d1
  1543.         bhi.s    subper    ;curr. period > target period
  1544.         move.l    #AUDIO_CONST,d1
  1545.         move.l    d1,d0
  1546.         tst.w    trk_prevper(a5)
  1547.         beq.s    fx_03rts
  1548.         divu    trk_prevper(a5),d0
  1549.         sub.w    d4,d0
  1550.         bls.s    targreached    ;carry or zero set
  1551.         divu    d0,d1
  1552.         cmp.w    trk_porttrgper(a5),d1
  1553.         bcs.s    targnreach
  1554.         bra.s    targreached
  1555. subper:        move.l    #AUDIO_CONST,d1
  1556.         move.l    d1,d0
  1557.         tst.w    trk_prevper(a5)
  1558.         beq.s    fx_03rts
  1559.         divu    trk_prevper(a5),d0
  1560.         add.w    d4,d0
  1561.         beq.s    targreached
  1562.         divu    d0,d1
  1563.         cmp.w    trk_porttrgper(a5),d1
  1564.         bhi.s    targnreach
  1565. targreached:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  1566.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  1567. targnreach:    move.w    d1,trk_prevper(a5)
  1568. fx_03rts    rts
  1569. ;    **************************************** Effect 13 ******
  1570. fx_13:        cmp.b    #3,d3
  1571.         bge.s    fx_13rts    ;if counter < 3
  1572.         neg.w    d4
  1573.         move.w    d4,trk_vibradjust(a5)    ;subtract effect qual...
  1574. fx_13rts    rts
  1575. ;    *********************************************************
  1576. fx_0c:        tst.b    d3
  1577.         bne.s    fx_13rts
  1578. dvc_0        move.b    trk_prevvol(a5),d1
  1579.         rts
  1580. ;    **************************************** Effect 10 ******
  1581. fx_10:
  1582.     IFNE    MIDI
  1583.         tst.b    d3
  1584.         bne.s    fx_13rts
  1585.         move.w    d4,d0
  1586.         bra.w    _InitMIDIDump
  1587.     ENDC
  1588.     IFEQ    MIDI
  1589.         rts
  1590.     ENDC
  1591. ;    **************************************** Effect 18 ******
  1592. fx_18        cmp.b    d4,d3
  1593.         bne.s    fx_18rts
  1594.         clr.b    trk_prevvol(a5)
  1595. fx_18rts    rts
  1596. ;    **************************************** Effect 1F ******
  1597. fx_1f        move.b    d4,d1
  1598.         lsr.b    #4,d4        ;note delay
  1599.         beq.s    nonotedelay
  1600.         cmp.b    d4,d3        ;compare to counter
  1601.         blt.s    fx_18rts    ;tick not reached
  1602.         bne.s    nonotedelay
  1603.         bra    playfxnote    ;trigger note
  1604. nonotedelay    and.w    #$0f,d1        ;retrig?
  1605.         beq.s    fx_18rts
  1606.         moveq    #0,d0
  1607.         move.b    d3,d0
  1608.         divu    d1,d0
  1609.         swap    d0        ;get modulo of counter/tick
  1610.         tst.w    d0
  1611.         bne.s    fx_18rts
  1612.         bra    playfxnote    ;retrigger
  1613. ;    **************************************** Effect 20 ******
  1614.         XREF    Mix_FX20
  1615. fx_20        tst.b    d3
  1616.         bne.s    fx_20rts
  1617.         move.b    d4,d0
  1618.         ext.w    d0
  1619.         jmp    Mix_FX20(pc)
  1620. fx_20rts    rts
  1621. ;    **************************************** Effect 0F ******
  1622. ;    see below...
  1623. ;    *********************************************************
  1624.  
  1625. ; *******************************************************************
  1626. ; UpdatePerVol:    Update audio registers (period & volume) after FX
  1627. ; *******************************************************************
  1628. ; args:        a6 = DB            d7 = channel #
  1629. ;        a5 = track data
  1630. ; scratches:    d0, d1, a0, d5
  1631. UpdatePerVol    cmp.w    maxaudiotrk-DB(a6),d7
  1632.         bge.s    plr_upv_rts
  1633.         move.w    trk_prevper(a5),d5
  1634.     IFNE    SYNTH
  1635.         move.l    trk_synthptr(a5),d0
  1636.         beq.s    plr_upv_nosynth
  1637.         move.l    a1,-(sp)
  1638.         bsr.w    synth_start
  1639.         move.l    (sp)+,a1
  1640.     ENDC
  1641. plr_upv_nosynth    add.w    trk_vibradjust(a5),d5
  1642.         sub.w    trk_arpadjust(a5),d5
  1643.         clr.l    trk_vibradjust(a5)    ;clr both adjusts
  1644.         moveq    #0,d0
  1645.         move.b    trk_tempvol(a5),d0
  1646.         bpl.s    plr_upv_setvol
  1647.         move.b    trk_prevvol(a5),d0
  1648. plr_upv_setvol    st    trk_tempvol(a5)
  1649. ; -------- GetRelVol: Calculate track volume -----------------------------
  1650. ; track # = d7, note vol = d0, song = a4
  1651.     IFNE    RELVOL
  1652.         mulu    trk_trackvol(a5),d0    ;d0 = master v. * track v. * volume
  1653.         lsr.w    #8,d0
  1654.     ENDC
  1655.         XREF    _MixSetTrkPeriod,_MixSetTrkVol
  1656.         move.l    a1,-(sp)
  1657.         jsr    _MixSetTrkVol(pc)
  1658.         movea.l    (sp)+,a1
  1659.         move.w    d5,d1
  1660.         jmp    _MixSetTrkPeriod(pc)
  1661. plr_upv_rts    rts
  1662.  
  1663. ; **** a separate routine for handling command 0F
  1664. fx_0f        cmp.b    #$f1,d4
  1665.         bne.s    no0ff1
  1666.         cmp.b    #3,d3
  1667.         beq.s    playfxnote
  1668.         rts
  1669. no0ff1:        cmp.b    #$f2,d4
  1670.         bne.s    no0ff2
  1671.         cmp.b    #3,d3
  1672.         beq.s    playfxnote
  1673.         rts
  1674. no0ff2:        cmp.b    #$f3,d4
  1675.         bne.s    no0ff3
  1676.         move.b    d3,d0
  1677.         beq.s    cF_rts
  1678.         and.b    #1,d0        ;is 2 or 4
  1679.         bne.s    cF_rts
  1680. playfxnote:    moveq    #0,d1
  1681.         move.b    trk_currnote(a5),d1    ;get note # of curr. note
  1682.         beq.s    cF_rts
  1683.         move.b    trk_noteoffcnt(a5),d0    ;get hold counter
  1684.         bmi.s    pfxn_nohold        ;no hold, or hold over
  1685.         add.b    d3,d0            ;increase by counter val
  1686.         bra.s    pfxn_hold
  1687. pfxn_nohold    move.b    trk_inithold(a5),d0    ;get initial hold
  1688.         bne.s    pfxn_hold
  1689.         st    d0
  1690. pfxn_hold    move.b    d0,trk_noteoffcnt(a5)
  1691.         movem.l    a1/a3/d2-d3/d5-d6,-(sp)
  1692.         moveq    #0,d3
  1693.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  1694.         movea.l    trk_previnstra(a5),a3
  1695.         bsr    _PlayNote
  1696.         movem.l    (sp)+,a1/a3/d2-d3/d5-d6
  1697. cF_rts        rts
  1698. no0ff3:        cmp.b    #$f4,d4        ;triplet cmd 1
  1699.         bne.s    no0ff4
  1700.         moveq    #0,d0
  1701.         move.b    msng_tempo2(a4),d0
  1702.         divu    #3,d0
  1703.         cmp.b    d0,d3
  1704.         beq.s    playfxnote
  1705.         rts
  1706. no0ff4        cmp.b    #$f5,d4        ;triplet cmd 2
  1707.         bne.s    no0ff5
  1708.         moveq    #0,d0
  1709.         move.b    msng_tempo2(a4),d0
  1710.         divu    #3,d0
  1711.         add.w    d0,d0
  1712.         cmp.b    d0,d3
  1713.         beq.s    playfxnote
  1714.         rts
  1715. no0ff5        cmp.b    #$f7,d4
  1716.         bne.s    no0ff7
  1717.     IFNE    MIDI
  1718.         tst.b    d3
  1719.         bne.s    1$
  1720.         tst.b    sysx-DB(a6)
  1721.         beq.s    1$
  1722.         addq.w    #1,blkdelay-DB(a6)
  1723.     ENDC
  1724. 1$        rts
  1725. no0ff7        cmp.b    #$f8,d4        ;f8 = filter off
  1726.         beq.s    plr_filteroff
  1727.         cmp.b    #$f9,d4        ;f9 = filter on
  1728.         bne.s    cF_rts
  1729.         bclr    #1,$bfe001
  1730.         bset    #0,msng_flags(a4)
  1731.         rts
  1732. plr_filteroff:    bset    #1,$bfe001
  1733.         bclr    #0,msng_flags(a4)
  1734.         rts
  1735.  
  1736. ; -------- AUDIO DMA ROUTINE ---------------------------------------------
  1737. _StartDMA:    ;Only used for triggering MIDI notes
  1738.     IFNE    MIDI
  1739.         lea    bytesinnotebuff-DB(a6),a0
  1740.         move.w    (a0)+,d0
  1741.         bne.w    _AddMIDId
  1742.         rts
  1743.     ENDC
  1744.  
  1745. _SetTempo:
  1746.         XREF    _SetMixTempo
  1747.         movea.l    a4,a0
  1748.         jmp    _SetMixTempo(pc)
  1749.  
  1750.     IFNE    MIDI
  1751. MIDIFX        add.b    d0,d0    ;* 2
  1752.         move.w    midicmd_table(pc,d0.w),d0
  1753.         jmp    midifx(pc,d0.w)
  1754. midifx        
  1755. midicmd_table    dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  1756.         dc.w    mfx_05-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  1757.         dc.w    mfx_0a-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_0d-midifx,mfx_0e-midifx
  1758.         dc.w    mfx_0f-midifx
  1759.         dc.w    mfx_10-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_13-midifx
  1760.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_17-midifx
  1761.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  1762.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,fx_1f-midifx
  1763.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  1764.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  1765.         dc.w    mfx_rts-midifx,mfx_31-midifx,mfx_32-midifx,mfx_33-midifx,mfx_34-midifx,mfx_35-midifx,mfx_36-midifx,mfx_37-midifx
  1766.         dc.w    mfx_38-midifx,mfx_39-midifx,mfx_3A-midifx,mfx_3B-midifx,mfx_3C-midifx,mfx_3D-midifx,mfx_3E-midifx,mfx_3F-midifx
  1767.  
  1768. mfx_01        lea    prevmidipbend-DB(a6),a0
  1769.         moveq    #0,d1
  1770.         move.b    trk_prevmidich(a5),d1    ;get previous midi channel
  1771.         add.b    d1,d1        ;UWORD index
  1772.         tst.b    d4        ;x100??
  1773.         beq.s    resetpbend
  1774.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  1775.         lsl.w    #3,d4        ;multiply bend value by 8
  1776.         add.w    d4,d0
  1777.         cmp.w    #$3fff,d0
  1778.         bls.s    bendpitch
  1779.         move.w    #$3fff,d0
  1780. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  1781.         lsr.b    #1,d1        ;back to UBYTE
  1782.         or.b    #$e0,d1
  1783.         lea    noteondata-DB(a6),a0
  1784.         move.b    d1,(a0)        ;midi command & channel
  1785.         move.b    d0,1(a0)    ;lower value
  1786.         and.b    #$7f,1(a0)    ;clear bit 7
  1787.         lsr.w    #7,d0
  1788.         and.b    #$7f,d0        ;clr bit 7
  1789.         move.b    d0,2(a0)    ;higher 7 bits
  1790.         moveq    #3,d0
  1791.         bra.w    _AddMIDId
  1792.  
  1793. mfx_02        lea    prevmidipbend-DB(a6),a0
  1794.         moveq    #0,d1
  1795.         move.b    trk_prevmidich(a5),d1
  1796.         add.b    d1,d1
  1797.         tst.b    d4
  1798.         beq.s    resetpbend    ;x200??
  1799.         move.w    0(a0,d1.w),d0
  1800.         lsl.w    #3,d4
  1801.         sub.w    d4,d0
  1802.         bpl.s    bendpitch    ;not under 0
  1803.         moveq    #0,d0
  1804.         bra.s    bendpitch
  1805. resetpbend:    tst.b    d3        ;d3 = counter (remember??)
  1806.         bne.s    mfx_rts
  1807.         move.w    #$2000,d0
  1808.         bra.s    bendpitch
  1809. mfx_rts        rts
  1810. mfx_13
  1811. mfx_03        tst.b    d3
  1812.         bne.s    mfx_rts
  1813.         lea    prevmidipbend-DB(a6),a0
  1814.         moveq    #0,d1
  1815.         move.b    trk_prevmidich(a5),d1
  1816.         add.b    d1,d1
  1817.         move.b    d4,d0
  1818.         add.b    #128,d0
  1819.         lsl.w    #6,d0
  1820.         bra.s    bendpitch
  1821.  
  1822. mfx_0d        tst.b    d3
  1823.         bne.s    mfx_rts
  1824.         lea    noteondata+1-DB(a6),a0    ;CHANNEL AFTERTOUCH
  1825.         move.b    d4,(a0)    ;value
  1826.         bmi.s    mfx_rts
  1827.         move.b    trk_prevmidich(a5),-(a0)
  1828.         or.b    #$d0,(a0)
  1829.         moveq    #2,d0
  1830.         bra.w    _AddMIDId
  1831.  
  1832. mfx_0a        tst.b    d3
  1833.         bne.s    mfx_rts
  1834.         lea    noteondata+2-DB(a6),a0    ;POLYPHONIC AFTERTOUCH
  1835.         and.b    #$7f,d4
  1836.         move.b    d4,(a0)
  1837.         move.b    trk_prevmidin(a5),-(a0)
  1838.         ble.s    mfx_rts
  1839.         move.b    trk_prevmidich(a5),-(a0)
  1840.         or.b    #$A0,(a0)
  1841.         moveq    #3,d0
  1842.         bra.w    _AddMIDId
  1843.  
  1844. mfx_17        moveq    #$07,d0        ;07 = VOLUME
  1845.         bra.s    pushctrldata
  1846.  
  1847. mfx_04        moveq    #$01,d0        ;01 = MODULATION WHEEL
  1848.         bra.s    pushctrldata
  1849.  
  1850. mfx_0e        moveq    #$0a,d0
  1851. pushctrldata    tst.b    d3        ;do it only once in a note
  1852.         bne.s    mfx_rts2    ;(when counter = 0)
  1853. pushctrld_nochk    lea    noteondata+2-DB(a6),a0 ;push "control change" data,
  1854.         move.b    d4,(a0)        ;second databyte
  1855.         bmi.s    mfx_rts2    ;$0 - $7F only
  1856.         move.b    d0,-(a0)    ;1st databyte
  1857.         move.b    trk_prevmidich(a5),-(a0)    ;MIDI channel
  1858.         or.b    #$b0,(a0)    ;command (B)
  1859.         moveq    #3,d0
  1860.         bra.w    _AddMIDId
  1861.  
  1862. mfx_05        and.b    #$7f,d4        ;set contr. value of curr. MIDI ch.
  1863.         move.b    trk_prevmidich(a5),d6
  1864.         lea    midicontrnum-DB(a6),a0
  1865.         adda.w    d6,a0
  1866.         move.b    d4,(a0)
  1867. mfx_rts2    rts
  1868.  
  1869. mfx_0f        cmp.b    #$fa,d4        ;hold pedal ON
  1870.         bne.s    nomffa
  1871.         moveq    #$40,d0
  1872.         moveq    #$7f,d4
  1873.         bra.s    pushctrldata
  1874. nomffa        cmp.b    #$fb,d4        ;hold pedal OFF
  1875.         bne.w    fx_0f
  1876.         moveq    #$40,d0
  1877.         moveq    #$00,d4
  1878.         bra.s    pushctrldata
  1879.  
  1880. mfx_00        tst.b    d4
  1881.         beq.s    mfx_rts2
  1882.         and.b    #$7f,d4
  1883.         move.b    trk_prevmidich(a5),d6
  1884.         lea    midicontrnum-DB(a6),a0
  1885.         move.b    0(a0,d6.w),d0
  1886.         bra.s    pushctrldata
  1887.  
  1888. mfx_10        tst.b    d3
  1889.         bne.s    mfx_rts2
  1890.         move.w    d4,d0
  1891.         bra.w    _InitMIDIDump
  1892.  
  1893. ; *** Command 3cxx handling
  1894.  
  1895. mfx_31        moveq    #0,d0
  1896.         bra.s    mfx_3x
  1897. mfx_32        moveq    #sizeof_mcs,d0
  1898.         bra.s    mfx_3x
  1899. mfx_33        moveq    #sizeof_mcs*2,d0
  1900.         bra.s    mfx_3x
  1901. mfx_34        moveq    #sizeof_mcs*3,d0
  1902.         bra.s    mfx_3x
  1903. mfx_35        moveq    #sizeof_mcs*4,d0
  1904.         bra.s    mfx_3x
  1905. mfx_36        moveq    #sizeof_mcs*5,d0
  1906.         bra.s    mfx_3x
  1907. mfx_37        moveq    #sizeof_mcs*6,d0
  1908.         bra.s    mfx_3x
  1909. mfx_38        moveq    #sizeof_mcs*7,d0
  1910.         bra.s    mfx_3x
  1911. mfx_39        moveq    #sizeof_mcs*8,d0
  1912.         bra.s    mfx_3x
  1913. mfx_3A        moveq    #sizeof_mcs*9,d0
  1914.         bra.s    mfx_3x
  1915. mfx_3B        moveq    #sizeof_mcs*10,d0
  1916.         bra.s    mfx_3x
  1917. mfx_3C        moveq    #sizeof_mcs*11,d0
  1918.         bra.s    mfx_3x
  1919. mfx_3D        moveq    #sizeof_mcs*12,d0
  1920.         bra.s    mfx_3x
  1921. mfx_3E        moveq    #sizeof_mcs*13,d0
  1922.         bra.s    mfx_3x
  1923. mfx_3F        moveq    #sizeof_mcs*14,d0
  1924. mfx_3x        tst.b    d3    ;counter?
  1925.         bne.w    mcs_notype5
  1926.         lea    cmd3xsettings-DB(a6),a0
  1927.         adda.w    d0,a0
  1928.         move.w    mcs_controller(a0),d1
  1929.         move.b    mcs_type(a0),d0
  1930.         bne.s    mcs_notype0
  1931. ; *** MCS type: STD (MSB)
  1932.         cmp.w    #$7F,d1
  1933.         bhi.s    1$
  1934.         move.b    d1,d0
  1935.         bra    pushctrld_nochk
  1936. 1$        rts
  1937. mcs_notype0    subq.b    #1,d0
  1938.         bne.s    mcs_notype1
  1939. ; *** MCS type: STD (LSB)
  1940.         cmp.w    #$7F,d1
  1941.         bhi.s    1$
  1942.         cmp.w    #$1F,d1
  1943.         bhi.s    2$
  1944.         add.w    #$20,d1        ;if contr. num was 0 - 1F, add $20 to get contr. LSB
  1945. 2$        move.b    d1,d0
  1946.         bra    pushctrld_nochk
  1947. 1$        rts
  1948. mcs_notype1    subq.b    #1,d0
  1949.         bne.s    mcs_notype2
  1950. ; *** MCS type: RPN (MSB)
  1951.         move.l    d2,-(sp)
  1952.         move.w    d1,d2
  1953.         addq.w    #1,d2        ;ctrlr num + 1
  1954.         lea    noteondata-DB(a6),a0
  1955.         moveq    #0,d0
  1956.         move.b    trk_prevmidich(a5),d0
  1957.         lea    prevmidiptype-DB(a6),a1
  1958.         bclr    #0,0(a1,d0.w)    ;test last parameter: RPN or NRPN?, set RPN
  1959.         lea    prevmidipn-DB(a6),a1 ;load parameter address in A1
  1960.         adda.w    d0,a1
  1961.         adda.w    d0,a1
  1962.         bne.s    1$        ;NRPN... send full ident
  1963.         cmp.w    (a1),d2        ;the same parameter number?
  1964.         bne.s    1$        ;no.. send param. number
  1965.         or.b    #$B0,d0
  1966.         move.b    d0,(a0)+
  1967.         moveq    #3,d0
  1968.         bra.s    2$
  1969. 1$        move.w    d2,(a1)
  1970.         or.b    #$B0,d0
  1971.         move.b    d0,(a0)+
  1972.         move.b    #$64,(a0)+    ;RPN LSB
  1973.         move.b    d1,(a0)
  1974.         and.b    #$7F,(a0)+    ;lower 7 bits of ctrlr number
  1975.         lsr.w    #7,d1
  1976.         move.b    #$65,(a0)+    ;RPN MSB
  1977.         move.b    d1,(a0)+
  1978.         moveq    #7,d0
  1979. 2$        move.b    #$06,(a0)+    ;data entry, MSB
  1980.         move.b    d4,(a0)
  1981.         lea    noteondata-DB(a6),a0
  1982.         move.l    (sp)+,d2
  1983.         bra.w    _AddMIDId
  1984. mcs_notype2    subq.b    #1,d0
  1985.         bne.s    mcs_notype3
  1986. ; *** MCS type: RPN (LSB)
  1987.         move.l    d2,-(sp)
  1988.         move.w    d1,d2
  1989.         addq.w    #1,d2        ;ctrlr num + 1
  1990.         lea    noteondata-DB(a6),a0
  1991.         moveq    #0,d0
  1992.         move.b    trk_prevmidich(a5),d0
  1993.         lea    prevmidiptype-DB(a6),a1
  1994.         bclr    #0,0(a1,d0.w)    ;test last parameter: RPN or NRPN?, set RPN
  1995.         lea    prevmidipn-DB(a6),a1 ;load parameter address in A1
  1996.         adda.w    d0,a1
  1997.         adda.w    d0,a1
  1998.         bne.s    1$        ;NRPN... send full ident
  1999.         cmp.w    (a1),d2        ;the same parameter number?
  2000.         bne.s    1$        ;no.. send param. number
  2001.         or.b    #$B0,d0
  2002.         move.b    d0,(a0)+
  2003.         moveq    #3,d0
  2004.         bra.s    2$
  2005. 1$        move.w    d2,(a1)
  2006.         or.b    #$B0,d0
  2007.         move.b    d0,(a0)+
  2008.         move.b    #$64,(a0)+    ;RPN LSB
  2009.         move.b    d1,(a0)
  2010.         and.b    #$7F,(a0)+    ;lower 7 bits of ctrlr number
  2011.         lsr.w    #7,d1
  2012.         move.b    #$65,(a0)+    ;RPN MSB
  2013.         move.b    d1,(a0)+
  2014.         moveq    #7,d0
  2015. 2$        move.b    #$26,(a0)+    ;data entry, LSB
  2016.         move.b    d4,(a0)
  2017.         lea    noteondata-DB(a6),a0
  2018.         move.l    (sp)+,d2
  2019.         bra.w    _AddMIDId
  2020. mcs_notype3    subq.b    #1,d0
  2021.         bne.s    mcs_notype4
  2022. ; *** MCS type: NRPN (MSB)
  2023.         move.l    d2,-(sp)
  2024.         move.w    d1,d2
  2025.         addq.w    #1,d2        ;ctrlr num + 1
  2026.         lea    noteondata-DB(a6),a0
  2027.         moveq    #0,d0
  2028.         move.b    trk_prevmidich(a5),d0
  2029.         lea    prevmidiptype-DB(a6),a1
  2030.         bset    #0,0(a1,d0.w)    ;test last parameter: RPN or NRPN?, set NRPN
  2031.         lea    prevmidipn-DB(a6),a1 ;load parameter address in A1
  2032.         adda.w    d0,a1
  2033.         adda.w    d0,a1
  2034.         beq.s    1$        ;RPN... send full ident
  2035.         cmp.w    (a1),d2        ;the same parameter number?
  2036.         bne.s    1$        ;no.. send param. number
  2037.         or.b    #$B0,d0
  2038.         move.b    d0,(a0)+
  2039.         moveq    #3,d0
  2040.         bra.s    2$
  2041. 1$        move.w    d2,(a1)
  2042.         or.b    #$B0,d0
  2043.         move.b    d0,(a0)+
  2044.         move.b    #$62,(a0)+    ;NRPN LSB
  2045.         move.b    d1,(a0)
  2046.         and.b    #$7F,(a0)+    ;lower 7 bits of ctrlr number
  2047.         lsr.w    #7,d1
  2048.         move.b    #$63,(a0)+    ;NRPN MSB
  2049.         move.b    d1,(a0)+
  2050.         moveq    #7,d0
  2051. 2$        move.b    #$06,(a0)+    ;data entry, MSB
  2052.         move.b    d4,(a0)
  2053.         lea    noteondata-DB(a6),a0
  2054.         move.l    (sp)+,d2
  2055.         bra.w    _AddMIDId
  2056. mcs_notype4    subq.b    #1,d0
  2057.         bne.s    mcs_notype5
  2058. ; *** MCS type: NRPN (MSB)
  2059.         move.l    d2,-(sp)
  2060.         move.w    d1,d2
  2061.         addq.w    #1,d2        ;ctrlr num + 1
  2062.         lea    noteondata-DB(a6),a0
  2063.         moveq    #0,d0
  2064.         move.b    trk_prevmidich(a5),d0
  2065.         lea    prevmidiptype-DB(a6),a1
  2066.         bset    #0,0(a1,d0.w)    ;test last parameter: RPN or NRPN?, set NRPN
  2067.         lea    prevmidipn-DB(a6),a1 ;load parameter address in A1
  2068.         adda.w    d0,a1
  2069.         adda.w    d0,a1
  2070.         beq.s    1$        ;RPN... send full ident
  2071.         cmp.w    (a1),d2        ;the same parameter number?
  2072.         bne.s    1$        ;no.. send param. number
  2073.         or.b    #$B0,d0
  2074.         move.b    d0,(a0)+
  2075.         moveq    #3,d0
  2076.         bra.s    2$
  2077. 1$        move.w    d2,(a1)
  2078.         or.b    #$B0,d0
  2079.         move.b    d0,(a0)+
  2080.         move.b    #$62,(a0)+    ;NRPN LSB
  2081.         move.b    d1,(a0)
  2082.         and.b    #$7F,(a0)+    ;lower 7 bits of ctrlr number
  2083.         lsr.w    #7,d1
  2084.         move.b    #$63,(a0)+    ;NRPN MSB
  2085.         move.b    d1,(a0)+
  2086.         moveq    #7,d0
  2087. 2$        move.b    #$26,(a0)+    ;data entry, MSB
  2088.         move.b    d4,(a0)
  2089.         lea    noteondata-DB(a6),a0
  2090.         move.l    (sp)+,d2
  2091.         bra.w    _AddMIDId
  2092. mcs_notype5    rts
  2093.  
  2094.  
  2095. _ResetMIDI:    movem.l    d2/a2/a6,-(sp)
  2096.         movea.l    4.w,a6        ;ExecBase
  2097.         jsr    -$78(a6)    ;Disable()
  2098.         lea    DB,a6
  2099. ; Clear preset memory
  2100.         lea    prevmidicpres-DB(a6),a0
  2101.         moveq    #7,d2
  2102. RM_loop0    clr.l    (a0)+    ;force presets to be set again
  2103.         dbf    d2,RM_loop0
  2104.         clr.b    lastcmdbyte
  2105. ; Reset pitchbenders & modulation wheels
  2106.         lea    midiresd-DB(a6),a2
  2107.         move.b    #$e0,(a2)
  2108.         move.b    #$b0,3(a2)
  2109.         moveq    #15,d2
  2110. respbendl:    movea.l    a2,a0
  2111.         moveq    #6,d0
  2112.         bsr.w    _AddMIDId
  2113.         addq.b    #1,(a2)
  2114.         addq.b    #1,3(a2)
  2115.         dbf    d2,respbendl
  2116.         lea    prevmidipbend-DB(a6),a2
  2117.         moveq    #15,d2
  2118. 1$        move.w    #$2000,(a2)+
  2119.         dbf    d2,1$
  2120. ; Clear parameters (set to undefined)
  2121.         lea    prevmidipn-DB(a6),a2
  2122.         lea    prevmidiptype-DB(a6),a0
  2123.         moveq    #15,d2
  2124. 2$        clr.w    (a2)+
  2125.         clr.b    (a0)+
  2126.         dbf    d2,2$
  2127. ; Clear dump variables
  2128.         clr.b    sysx-DB(a6)
  2129.         lea    dumpqueue-DB(a6),a0
  2130.         move.l    a0,dqreadptr-DB(a6)
  2131.         move.l    a0,dqwriteptr-DB(a6)
  2132.         clr.w    dqentries-DB(a6)
  2133. ; Enable & exit
  2134.         movea.l    4.w,a6
  2135.         jsr    -$7e(a6)    ;Enable()
  2136.         movem.l    (sp)+,d2/a2/a6
  2137.         rts
  2138.     ENDC
  2139.  
  2140. ; *************************************************************************
  2141. ; *************************************************************************
  2142. ; ***********          P U B L I C   F U N C T I O N S          ***********
  2143. ; *************************************************************************
  2144. ; *************************************************************************
  2145.  
  2146.         XDEF    _InitModuleM,_PlayModuleM
  2147.         XDEF    _InitPlayerM,_RemPlayerM,_StopPlayerM
  2148.         XDEF    _ContModuleM
  2149.  
  2150. ; *************************************************************************
  2151. ; InitModule(a0 = module) -- extract expansion data etc.. from a module
  2152. ; *************************************************************************
  2153.  
  2154. _InitModuleM:    movem.l    a2-a3/d2,-(sp)
  2155.         move.l    a0,-(sp)
  2156.         beq    IM_exit            ;0 => xit
  2157.     IFNE    RELVOL
  2158.         movea.l    mmd_songinfo(a0),a1    ;MMD0song
  2159.         move.b    msng_mastervol(a1),d0    ;d0 = mastervol
  2160.         ext.w    d0
  2161.         lea    trackdataptrs,a2
  2162.         cmp.b    #'2',3(a0)        ;MMD2?
  2163.         bcs.s    IM_mmd01
  2164.         move.w    msng_numtracks(a1),d1
  2165.         subq.w    #1,d1
  2166.         movea.l    msng_trkvoltbl(a1),a1
  2167.         bra.s    IM_loop0
  2168. IM_mmd01    lea    msng_trkvol(a1),a1    ;a1 = trkvol
  2169.         moveq    #MAX_MMD1_TRACKS-1,d1
  2170. IM_loop0    move.b    (a1)+,d2    ;get vol...
  2171.         ext.w    d2
  2172.         move.l    (a2)+,a3    ;pointer to track data
  2173.         mulu    d0,d2        ;mastervol * trackvol
  2174.         lsr.w    #4,d2
  2175.         move.w    d2,trk_trackvol(a3)
  2176.         dbf    d1,IM_loop0
  2177.     ENDC
  2178.     IFNE    SYNTH
  2179.         lea    trackdataptrs,a2
  2180.         moveq    #63,d1
  2181. IM_loop1    move.l    (a2)+,a3
  2182.         clr.l    trk_synthptr(a3)
  2183.         clr.b    trk_synthtype(a3)
  2184.         dbf    d1,IM_loop1
  2185.     ENDC
  2186.         lea    holdvals,a2
  2187.         movea.l    a0,a3
  2188.         move.l    mmd_expdata(a0),d0    ;expdata...
  2189.         beq    IM_clrhlddec        ;none here
  2190.         move.l    d0,a1
  2191.         move.l    4(a1),d0        ;exp_smp
  2192.         beq    IM_clrhlddec    ;again.. nothing
  2193.         move.l    d0,a0        ;InstrExt...
  2194.         move.w    8(a1),d2    ;# of entries
  2195.         beq    IM_clrhlddec
  2196. ; perhaps >63 instruments are supported in the future... just in case...
  2197.         cmp.w    #63,d2
  2198.         ble.s    1$
  2199.         moveq    #63,d2
  2200. 1$        move.l    a4,-(sp)
  2201.         lea    rptrptlen,a4
  2202.         subq.w    #1,d2        ;-1 (for dbf)
  2203.         move.w    10(a1),d0    ;entry size
  2204.         movea.l    mmd_songinfo(a3),a3    ;MMD0song
  2205.     IFNE    MIDI
  2206.         lea    4*63(a2),a1    ;pointer to ext_midipsets...
  2207.     ENDC
  2208. IM_loop2    clr.b    2*63(a2)        ;clear finetune
  2209.         cmp.w    #3,d0
  2210.         ble.s    IM_noftune
  2211.         move.b    3(a0),126(a2)    ;InstrExt.finetune -> finetune
  2212. IM_noftune    clr.b    3*63(a2)    ;clear flags
  2213.         cmp.w    #6,d0
  2214.         blt.s    IM_noflags
  2215.         move.b    5(a0),3*63(a2)    ;InstrExt.flags -> flags
  2216.         bra.s    IM_gotflags
  2217. IM_noflags    cmp.w    #1,inst_replen(a3)
  2218.         bls.s    IM_gotflags
  2219.         bset    #0,3*63(a2)
  2220. IM_gotflags    clr.b    6*63(a2)    ;Initally OUTPUT_STD
  2221.         cmp.w    #9,d0
  2222.         blt.s    IM_noopdev
  2223.         move.b    8(a0),6*63(a2)    ;get InstrExt.output_device
  2224. IM_noopdev    cmp.w    #18,d0
  2225.         blt.s    IM_nolongrpt
  2226.         move.l    10(a0),(a4)+    ;rpt
  2227.         move.l    14(a0),(a4)+    ;rptlen
  2228.         bra.s    IM_gotlongrpt
  2229. IM_nolongrpt    moveq    #0,d1
  2230.         move.w    inst_repeat(a3),d1
  2231.         add.l    d1,d1
  2232.         move.l    d1,(a4)+
  2233.         moveq    #0,d1
  2234.         move.w    inst_replen(a3),d1
  2235.         add.l    d1,d1
  2236.         move.l    d1,(a4)+
  2237. IM_gotlongrpt
  2238.     IFNE    MIDI
  2239.         cmp.w    #2,d0
  2240.         ble.s    IM_nsmnoff
  2241.         tst.b    2(a0)        ;suppress MIDI note off?
  2242.         beq.s    IM_nsmnoff
  2243.         bset    #7,inst_midich(a3)
  2244. IM_nsmnoff    move.b    inst_midipreset(a3),d1
  2245.         ext.w    d1
  2246.         move.w    d1,(a1)
  2247.         cmp.w    #8,d0
  2248.         ble.s    IM_nolongpset
  2249.         move.w    6(a0),(a1)    ;-> ext_midipsets
  2250.         btst    #1,5(a0)
  2251.         beq.s    IM_nolongpset
  2252.         bset    #6,inst_midich(a3)
  2253. IM_nolongpset    addq.l    #2,a1
  2254.     ENDC
  2255.         move.b    1(a0),63(a2)    ;InstrExt.decay -> decay
  2256.         move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  2257.         adda.w    d0,a0        ;ptr to next InstrExt
  2258.         addq.l    #8,a3        ;next instrument...
  2259.         dbf    d2,IM_loop2
  2260.         move.l    (sp)+,a4
  2261.         bra.s    IM_exit
  2262. IM_clrhlddec    move.w    #5*63+2*63+4*126-1,d0    ;no InstrExt => clear holdvals/decays
  2263. 1$        clr.b    (a2)+            ;..and finetunes/flags/ext_psets etc..
  2264.         dbf    d0,1$
  2265.         movea.l    (sp),a0
  2266. ; -------- For (very old) MMDs, with no InstrExt, set flags/SSFLG_LOOP,
  2267. ; -------- also copy inst_midipreset to ext_midipsets.
  2268.         movea.l    mmd_songinfo(a0),a3
  2269.         lea    flags,a2
  2270.         lea    rptrptlen,a0
  2271.     IFNE    MIDI
  2272.         lea    ext_midipsets,a1
  2273.     ENDC
  2274.         moveq    #62,d0
  2275. IM_loop4    cmp.w    #1,inst_replen(a3)
  2276.         bls.s    IM_noreptflg
  2277.         bset    #0,(a2)
  2278. IM_noreptflg    addq.l    #1,a2
  2279.     IFNE    MIDI
  2280.         move.b    inst_midipreset(a3),d1
  2281.         ext.w    d1
  2282.         move.w    d1,(a1)+
  2283.     ENDC
  2284.         moveq    #0,d1
  2285.         move.w    inst_repeat(a3),d1
  2286.         add.l    d1,d1
  2287.         move.l    d1,(a0)+
  2288.         move.w    inst_replen(a3),d1
  2289.         add.l    d1,d1
  2290.         move.l    d1,(a0)+
  2291.         addq.l    #8,a3        ;next inst
  2292.         dbf    d0,IM_loop4
  2293. IM_exit
  2294. ; -------- Get MIDI command 3x settings (if they exist)
  2295.     IFNE    MIDI
  2296.         movea.l    (sp),a0
  2297.         lea    cmd3xsettings,a2
  2298.         move.l    mmd_expdata(a0),d0
  2299.         beq.s    IM_c3_clr
  2300.         move.l    d0,a0
  2301.         move.l    64(a0),d0    ;mmdcmd3x
  2302.         beq.s    IM_c3_clr
  2303.         move.w    2(a0),d0    ;num_of_settings
  2304.         cmp.w    #15,d0
  2305.         bhi.s    1$
  2306.         moveq    #15,d0
  2307. 1$        move.l    4(a0),d1    ;ctrlr types
  2308.         beq.s    IM_c3_clr
  2309.         movea.l    d1,a1
  2310.         move.l    8(a0),d1    ;ctrlr numbers
  2311.         beq.s    IM_c3_clr
  2312.         movea.l    d1,a3
  2313.         subq.w    #1,d0
  2314.         bmi.s    IM_c3_clr
  2315. 2$        move.b    (a1)+,d1
  2316.         ext.w    d1
  2317.         move.w    d1,(a2)+
  2318.         move.w    (a3)+,(a2)+
  2319.         dbra    d0,2$
  2320.         bra.s    IM_c3_exit
  2321. IM_c3_clr    moveq    #15-1,d0
  2322. 1$        clr.l    (a2)+
  2323.         dbra    d0,1$
  2324. IM_c3_exit
  2325.     ENDC
  2326. ; -------- Exit
  2327.         addq.l    #4,sp
  2328.         movem.l    (sp)+,a2-a3/d2
  2329.         rts
  2330. ; *************************************************************************
  2331. ; InitPlayerM() -- allocate interrupt, audio, serial port etc...
  2332. ; *************************************************************************
  2333. _InitPlayerM:
  2334.     IFNE    MIDI
  2335.         bsr.w    _GetSerial
  2336.         tst.l    d0
  2337.         bne.s    IP_error
  2338.     ENDC
  2339.         bsr.w    _AudioInit
  2340.         tst.l    d0
  2341.         bne.s    IP_error
  2342.         rts
  2343. IP_error    bsr.s    _RemPlayerM
  2344.         moveq    #-1,d0
  2345.         rts
  2346. ; *************************************************************************
  2347. ; RemPlayerM() -- free interrupt, audio, serial port etc..
  2348. ; *************************************************************************
  2349. _RemPlayerM:    movem.l    a5/a6,-(sp)
  2350.         lea    DB,a5
  2351.         tst.b    audiodevopen-DB(a5)
  2352.         beq.s    RP_notimer    ;timer is not ours
  2353.         bsr.s    _StopPlayerM
  2354.         bsr.w    FreeMixBuffers
  2355.         clr.w    _mix_channels-DB(a5)
  2356.         movea.l    4.w,a6            ;ExecBase
  2357.         jsr    -$78(a6)        ;Disable()
  2358.         movea.l    _chinfo-DB(a5),a1
  2359.         clr.l    _chinfo-DB(a5)
  2360.         jsr    -$2B2(a6)        ;FreeVec
  2361.         movea.l    _voltable-DB(a5),a1
  2362.         clr.l    _voltable-DB(a5)
  2363.         jsr    -$2B2(a6)        ;FreeVec
  2364.         jsr    -$7E(a6)        ;Enable()
  2365.         movea.l    _frqtblmem-DB(a5),a1
  2366.         clr.l    _frqtblmem-DB(a5)
  2367.         jsr    -$2B2(a6)        ;FreeVec
  2368. RP_notimer:    bsr.w    _AudioRem
  2369.     IFNE    MIDI
  2370.         bsr.w    _FreeSerial
  2371.     ENDC
  2372.         movem.l    (sp)+,a5/a6
  2373.         rts
  2374. ; *************************************************************************
  2375. ; StopPlayerM() -- stop the music
  2376. ; *************************************************************************
  2377. _StopPlayerM:    move.l    a6,-(sp)
  2378.         lea    DB,a6
  2379.         tst.b    audiodevopen-DB(a6)
  2380.         beq.s    SP_end        ;res. alloc fail.
  2381.         bsr.w    StopMix
  2382.         move.l    _module-DB(a6),d0
  2383.         beq.s    SP_nomod
  2384.         move.l    d0,a0
  2385.         clr.w    mmd_pstate(a0)
  2386.         clr.l    _module-DB(a6)
  2387. SP_nomod
  2388.     IFNE    MIDI
  2389.         clr.b    lastcmdbyte-DB(a6)
  2390.     ENDC
  2391.         bsr.w    SoundOff
  2392. SP_end        movea.l    (sp)+,a6
  2393.         rts
  2394.  
  2395.  
  2396. _ContModuleM    tst.b    audiodevopen
  2397.         beq.s    SP_end
  2398.         move.l    a0,-(sp)
  2399.         bsr.w    SoundOff
  2400.         move.l    (sp)+,a0
  2401.         moveq    #0,d0
  2402.         bra.s    contpoint
  2403. ; *************************************************************************
  2404. ; PlayModuleM(a0 = module)  -- initialize & play it!
  2405. ; *************************************************************************
  2406. _PlayModuleM:    st    d0
  2407. contpoint    movem.l    a0/d0,-(sp)
  2408.         bsr    _InitModuleM
  2409.         movem.l    (sp)+,a0/d0
  2410.         movem.l    a4/a6,-(sp)
  2411.         lea    DB,a6
  2412.         tst.b    audiodevopen-DB(a6)
  2413.         beq    PM_err        ;resource allocation failure
  2414.         move.l    a0,d1
  2415.         beq    PM_err        ;module failure
  2416.         clr.l    _module-DB(a6)
  2417.     IFNE    MIDI
  2418.         clr.b    lastcmdbyte-DB(a6)
  2419.     ENDC
  2420.         move.w    _modnumm,d1
  2421.         beq.s    PM_modfound
  2422. PM_nextmod    tst.l    mmd_expdata(a0)
  2423.         beq.s    PM_modfound
  2424.         move.l    mmd_expdata(a0),a1
  2425.         tst.l    (a1)
  2426.         beq.s    PM_modfound        ;no more modules here!
  2427.         move.l    (a1),a0
  2428.         subq.w    #1,d1
  2429.         bgt.s    PM_nextmod
  2430. PM_modfound    cmp.b    #'T',3(a0)
  2431.         bne.s    PM_nomodT
  2432.         move.b    #'0',3(a0)    ;change MCNT to MCN0
  2433. PM_nomodT    movea.l    mmd_songinfo(a0),a1        ;song
  2434.         move.l    a1,_sng_struct-DB(a6)
  2435.         movea.l    a1,a4
  2436.         move.b    msng_tempo2(a1),mmd_counter(a0)    ;init counter
  2437.         tst.b    msng_flags2(a1)
  2438.         bpl.w    PM_err        ;does not use mixing... FAIL!
  2439.         btst    #0,msng_flags(a1)
  2440.         bne.s    PM_filon
  2441.         bset    #1,$bfe001
  2442.         bra.s    PM_filset
  2443. PM_filon    bclr    #1,$bfe001
  2444. PM_filset    tst.b    d0
  2445.         beq.s    PM_noclr
  2446.         clr.l    mmd_pline(a0)
  2447.         clr.l    rptline-DB(a6)
  2448.         clr.w    blkdelay-DB(a6)
  2449. ; ---------- Set 'pblock' and 'pseq' to correct values...
  2450. PM_noclr    move.w    mmd_psecnum(a0),d1
  2451.         move.l    a2,-(sp)        ;need extra register
  2452.         movea.l    msng_sections(a1),a2
  2453.         add.w    d1,d1
  2454.         move.w    0(a2,d1.w),d1        ;get sequence number
  2455.         add.w    d1,d1
  2456.         add.w    d1,d1
  2457.         move.w    d1,mmd_pseq(a0)
  2458.         movea.l    msng_pseqs(a1),a2
  2459.         movea.l    0(a2,d1.w),a2        ;PlaySeq...
  2460.         move.w    mmd_pseqnum(a0),d1
  2461.         add.w    d1,d1
  2462.         move.w    42(a2,d1.w),d1        ;and the correct block..
  2463.         move.l    (sp)+,a2
  2464.         move.w    d1,mmd_pblock(a0)
  2465.         move.w    #-1,mmd_pstate(a0)
  2466.         move.l    a0,_module-DB(a6)
  2467.         bsr.w    InitMix
  2468.         tst.l    d0
  2469.         bne.s    PM_err
  2470.         move.l    d2,-(sp)
  2471.         moveq    #0,d2
  2472.         move.b    _mix14bit-DB(a6),d2
  2473.         XREF    _StartAmigaMix
  2474.         jsr    _StartAmigaMix(pc)
  2475.         move.l    (sp)+,d2
  2476.         moveq    #0,d0
  2477.         movem.l    (sp)+,a4/a6
  2478.         rts
  2479. PM_err        moveq    #1,d0
  2480.         movem.l    (sp)+,a4/a6
  2481.         rts
  2482. ; *************************************************************************
  2483.  
  2484. _AudioInit:    movem.l    a4/a6/d3,-(sp)
  2485.         lea    DB,a4
  2486.         movea.l    4.w,a6
  2487.         lea    utilityname-DB(a4),a1
  2488.         moveq    #0,d0
  2489.         jsr    -$228(a6)    ;OpenLibrary()
  2490.         move.l    d0,UtBase
  2491.         beq.s    initerr
  2492. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  2493.     IFNE    AUDDEV
  2494.         moveq    #-1,d0
  2495.         jsr    -$14a(a6)    ;AllocSignal()
  2496.         tst.b    d0
  2497.         bmi.s    initerr
  2498.         move.b    d0,sigbitnum-DB(a4)
  2499. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  2500.         lea    allocport-DB(a4),a1
  2501.         move.b    d0,15(a1)    ;set mp_SigBit
  2502.         move.l    a1,-(sp)
  2503.         suba.l    a1,a1
  2504.         jsr    -$126(a6)    ;FindTask(0)
  2505.         move.l    (sp)+,a1
  2506.         move.l    d0,16(a1)    ;set mp_SigTask
  2507.         lea    reqlist-DB(a4),a0
  2508.         move.l    a0,(a0)        ;NEWLIST begins...
  2509.         addq.l    #4,(a0)
  2510.         clr.l    4(a0)
  2511.         move.l    a0,8(a0)    ;NEWLIST ends...
  2512. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  2513.         lea    allocreq-DB(a4),a1
  2514.         lea    audiodevname-DB(a4),a0
  2515.         moveq    #0,d0
  2516.         moveq    #0,d1
  2517.         movea.l    4.w,a6
  2518.         jsr    -$1bc(a6)    ;OpenDevice()
  2519.         tst.b    d0
  2520.         bne.w    initerr
  2521.     ENDC
  2522.         st    audiodevopen-DB(a4)
  2523.         moveq    #0,d0
  2524. initret:    movem.l    (sp)+,a4/a6/d3
  2525.         rts
  2526. initerr:    moveq    #1,d0
  2527.         bra.s    initret
  2528.  
  2529. _AudioRem:    movem.l    a5-a6,-(sp)
  2530.         lea    DB,a5
  2531.         movea.l    4.w,a6
  2532.         move.l    UtBase,d0
  2533.         beq.s    1$
  2534.         move.l    d0,a1
  2535.         jsr    -$19E(a6)    ;CloseLibrary
  2536.         clr.l    UtBase
  2537. 1$
  2538.     IFNE    AUDDEV
  2539.         tst.b    audiodevopen-DB(a5)
  2540.         beq.s    rem2
  2541.         move.w    #$000f,$dff096    ;stop audio DMA
  2542. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  2543.         lea    allocreq-DB(a5),a1
  2544.         jsr    -$1c2(a6)    ;CloseDevice()
  2545.         clr.b    audiodevopen-DB(a5)
  2546. rem2:        moveq    #0,d0
  2547.         move.b    sigbitnum-DB(a5),d0
  2548.         bmi.s    rem3
  2549. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  2550.         jsr    -$150(a6)    ;FreeSignal()
  2551.         st    sigbitnum-DB(a5)
  2552. rem3:
  2553.     ENDC
  2554.         movem.l    (sp)+,a5-a6
  2555.         rts
  2556.  
  2557. InitFreqTables    movem.l    a2-a3/d2/a6,-(sp)
  2558.         move.l    #6*12*2*16,d0
  2559.         moveq    #1,d1        ;MEMF_PUBLIC
  2560.         movea.l    4.w,a6
  2561.         jsr    -$2AC(a6)    ;AllocVec
  2562.         move.l    d0,_frqtblmem
  2563.         beq.s    ift_err
  2564.         lea    _freq_tables,a2
  2565.         movea.l    d0,a3
  2566.         moveq    #0,d2
  2567. 1$        move.l    a3,(a2)+
  2568.         move.l    d2,d0
  2569.         subq.l    #8,d0
  2570.         movea.l    UtBase,a0
  2571.         move.l    #509916,d1    ;finetune difference
  2572.         jsr    -$8A(a0)    ;SMult32()
  2573.         add.l    #68583572,d0    ;C-1 freq * 65536
  2574.         movea.l    a3,a0
  2575.         move.w    $128(a6),d1    ;SysBase->AttnFlags
  2576.         btst    #4,d1        ;68881?
  2577.         beq.s    2$
  2578.         XREF    _FillFreqTable_FP
  2579.         jsr    _FillFreqTable_FP(pc)
  2580.         bra.s    3$
  2581. 2$        move.l    #69433,d1    ;12th root of 2 * 65536
  2582.         XREF    _FillFreqTable
  2583.         jsr    _FillFreqTable(pc)
  2584. 3$        lea    6*12*2(a3),a3
  2585.         addq.l    #1,d2
  2586.         cmp.w    #16,d2
  2587.         blt.s    1$
  2588. ift_end        moveq    #0,d0
  2589.         movem.l    (sp)+,a2-a3/d2/a6
  2590.         rts
  2591. ift_err        moveq    #1,d0
  2592.         movem.l    (sp)+,a2-a3/d2/a6
  2593.         rts
  2594.  
  2595. ; DB in A6
  2596. FillVolTables    movem.l    d2-d5,-(sp)
  2597.         tst.l    _voltable-DB(a6)
  2598.         beq.s    fvt_crtnew
  2599.         move.w    msng_channels(a4),d0
  2600.         cmp.w    _prevnumch-DB(a6),d0
  2601.         bne.s    fvt_crtnew
  2602.         move.w    msng_voladj(a4),d0
  2603.         cmp.w    _prevadj-DB(a6),d0
  2604.         bne.s    fvt_crtnew
  2605.         move.l    msng_flags3(a4),d0
  2606.         move.l    d0,d1
  2607.         and.b    #1,d0    ;get FLAG3_STEREO
  2608.         cmp.b    _prevstereo-DB(a6),d0
  2609.         bne.s    fvt_crtnew
  2610.         and.b    #2,d1    ;get FLAG3_FREEPAN
  2611.         cmp.b    _prevfreepan-DB(a6),d1
  2612.         beq.w    fvt_end
  2613. fvt_crtnew    tst.l    _voltable-DB(a6)
  2614.         bne.s    1$
  2615.         move.l    #64*256*2,d0
  2616.         moveq    #1,d1    ;MEMF_PUBLIC
  2617.         move.l    a6,d5
  2618.         movea.l    4.w,a6
  2619.         jsr    -$2AC(a6)    ;AllocVec
  2620.         move.l    d5,a6
  2621.         move.l    d0,_voltable-DB(a6)
  2622.         beq.w    fvt_err
  2623. 1$        move.w    msng_channels(a4),d2
  2624.         move.w    d2,_prevnumch-DB(a6)
  2625.         move.w    msng_voladj(a4),_prevadj-DB(a6)
  2626.         move.l    msng_flags3(a4),d0
  2627.         move.l    d0,d1
  2628.         and.b    #1,d0    ;stereo
  2629.         move.b    d0,_prevstereo-DB(a6)
  2630.         and.b    #2,d1    ;freepan
  2631.         move.b    d1,_prevfreepan-DB(a6)
  2632. ;    if(sng->sg->mix_stereo && !sng->sg->mix_freepan && numch > 1) numch /= 2;
  2633.         tst.b    d0
  2634.         beq.s    fvt_nohalf
  2635.         tst.b    d1
  2636.         bne.s    fvt_nohalf
  2637.         cmp.w    #1,d2
  2638.         ble.s    fvt_nohalf
  2639.         lsr.w    #1,d2
  2640. fvt_nohalf
  2641. ; fill volume table
  2642.         mulu    #6400,d2
  2643.         movea.l    _voltable-DB(a6),a0    ;destination
  2644.         movea.l    UtBase-DB(a6),a1
  2645.         moveq    #0,d3        ;volcnt
  2646. fvt_outloop    moveq    #0,d4        ;svalcnt
  2647.         move.w    d3,d5
  2648.         addq.w    #1,d5        ;volcnt + 1...
  2649.         mulu    msng_voladj(a4),d5    ;* adj
  2650. fvt_inloop    move.b    d4,d0
  2651.         lsl.w    #8,d0
  2652.         muls    d5,d0
  2653.         move.l    d2,d1
  2654.         jsr    -$96(a1)    ;SDivMod32()
  2655.         move.w    d0,(a0)+
  2656.         addq.w    #1,d4
  2657.         cmp.w    #256,d4
  2658.         blt.s    fvt_inloop
  2659.         addq.w    #1,d3
  2660.         cmp.w    #64,d3
  2661.         blt.s    fvt_outloop
  2662. ; channel shift:
  2663.         moveq    #0,d5        ;newchshift
  2664.         move.w    msng_channels(a4),d0
  2665.         cmp.w    #2,d0
  2666.         blo.s    1$
  2667.         beq.s    2$
  2668.         addq.w    #2,d5
  2669.         cmp.w    #4,d0
  2670.         bls.s    1$
  2671.         addq.w    #1,d5
  2672.         cmp.w    #8,d0
  2673.         bls.s    1$
  2674.         addq.w    #1,d5
  2675.         cmp.w    #16,d0
  2676.         bls.s    1$
  2677.         addq.w    #1,d5
  2678.         cmp.w    #32,d0
  2679.         bls.s    1$
  2680. 2$        addq.w    #1,d5
  2681. 1$        btst    #0,msng_flags3+3(a4)
  2682.         beq.s    fvt_nostrshft
  2683.         btst    #1,msng_flags3+3(a4)
  2684.         bne.s    fvt_nostrshft
  2685.         tst.w    d5
  2686.         beq.s    fvt_nostrshft
  2687.         subq.w    #1,d5
  2688. fvt_nostrshft    move.w    msng_voladj(a4),d1
  2689. ;    test vol adj. above 100
  2690.         tst.w    d5
  2691.         beq.s    fvt_noabvol
  2692.         cmp.w    #200,d1
  2693.         blo.s    fvt_noabvol
  2694.         subq.w    #1,d5
  2695.         beq.s    fvt_noabvol
  2696.         cmp.w    #400,d1
  2697.         blo.s    fvt_noabvol
  2698.         subq.w    #1,d5
  2699.         beq.s    fvt_noabvol
  2700.         cmp.w    #800,d1
  2701.         blo.s    fvt_noabvol
  2702.         subq.w    #1,d5
  2703. fvt_noabvol
  2704. ;    test vol adj. below 100
  2705.         cmp.w    #100,d1
  2706.         bhs.s    fvt_nobevol
  2707.         addq.w    #1,d5
  2708.         cmp.w    #50,d1
  2709.         bhs.s    fvt_nobevol
  2710.         addq.w    #1,d5
  2711.         cmp.w    #25,d1
  2712.         bhs.s    fvt_nobevol
  2713.         addq.w    #1,d5
  2714.         cmp.w    #13,d1
  2715.         bhs.s    fvt_nobevol
  2716.         addq.w    #1,d5
  2717.         cmp.w    #7,d1
  2718.         bhs.s    fvt_nobevol
  2719.         addq.w    #1,d5
  2720.         cmp.w    #4,d1
  2721.         bhs.s    fvt_nobevol
  2722.         addq.w    #1,d5
  2723.         cmp.w    #2,d1
  2724.         bhs.s    fvt_nobevol
  2725.         addq.w    #1,d5
  2726. fvt_nobevol    move.w    d5,_chshift-DB(a6)
  2727. fvt_end        moveq    #0,d0
  2728.         movem.l    (sp)+,d2-d5
  2729.         rts
  2730. fvt_err        moveq    #1,d0
  2731.         movem.l    (sp)+,d2-d5
  2732.         rts
  2733.  
  2734. ; DB in A6
  2735. AllocEchoBuffer    ;echo length in d0
  2736.         movem.l    d2/d3,-(sp)
  2737.         move.w    _actualrate_hz-DB(a6),d1
  2738.         mulu    d1,d0
  2739.         movea.l    UtBase-DB(a6),a0
  2740.         moveq    #0,d1
  2741.         move.w    #1000,d1
  2742.         jsr    -$9c(a0)    ;UDivMod32()
  2743.         move.l    d0,d2        ;ebsz
  2744.         move.l    d2,d3
  2745.         add.l    d3,d3        ;actsz
  2746.         btst    #FLAG3B_STEREO,msng_flags3+3(a4)
  2747.         beq.s    1$
  2748.         add.l    d3,d3
  2749. 1$        move.l    d3,d0
  2750.         moveq    #1,d1    ;PUBLIC
  2751.         bset    #16,d1    ;CLEAR
  2752.         move.l    a6,d3
  2753.         movea.l    4.w,a6
  2754.         jsr    -$2AC(a6)    ;AllocVec
  2755.         move.l    d3,a6
  2756.         move.l    d0,_echobuffer-DB(a6)
  2757.         move.l    d2,_echobuffsz-DB(a6)
  2758.         clr.l    _echord-DB(a6)
  2759.         movem.l    (sp)+,d2/d3
  2760.         rts
  2761.  
  2762. ; DB in A6
  2763. FreeEchoBuffer    move.l    a6,-(sp)
  2764.         move.l    _echobuffer-DB(a6),a1
  2765.         clr.l    _echobuffer-DB(a6)
  2766.         movea.l    4.w,a6
  2767.         jsr    -$2B2(a6)    ;FreeVec
  2768.         move.l    (sp)+,a6
  2769.         rts
  2770.  
  2771. ; DB in A6
  2772. AllocMixBuffers    movem.l    d2/a2/a3/a6,-(sp)
  2773.         movea.l    a6,a3
  2774.         moveq    #2,d2        ;number of chip mem buffers
  2775.         btst    #FLAG3B_STEREO,msng_flags3+3(a4)
  2776.         beq.s    1$
  2777.         add.l    d2,d2    ;stereo... two buffers
  2778. 1$        tst.b    _mix14bit-DB(a3)
  2779.         beq.s    2$
  2780.         add.l    d2,d2    ;14bit... 4/8 buffers
  2781. 2$        lea    _chipbuff-DB(a3),a2
  2782.         movea.l    4.w,a6
  2783.         subq.w    #1,d2
  2784. 3$        move.l    _mixbuffsize-DB(a3),d0
  2785.         moveq    #3,d1    ;CHIP, PUBLIC
  2786.         bset    #16,d1    ;CLEAR
  2787.         jsr    -$2AC(a6)    ;AllocVec
  2788.         move.l    d0,(a2)+
  2789.         beq.s    amb_err
  2790.         dbra    d2,3$
  2791.         move.l    _mixbuffsize-DB(a3),d0
  2792.         add.l    d0,d0
  2793.         btst    #FLAG3B_STEREO,msng_flags3+3(a4)
  2794.         beq.s    4$
  2795.         add.l    d0,d0
  2796. 4$        move.l    d0,d2
  2797.         moveq    #1,d1    ;PUBLIC
  2798.         bset    #16,d1    ;CLEAR
  2799.         jsr    -$2AC(a6)    ;AllocVec
  2800.         move.l    d0,_mixbuff-DB(a3)
  2801.         beq.s    amb_err
  2802.         move.l    d2,d0
  2803.         moveq    #1,d1    ;PUBLIC
  2804.         bset    #16,d1    ;CLEAR
  2805.         jsr    -$2AC(a6)    ;AllocVec
  2806.         move.l    d0,_mixbuff+4-DB(a3)
  2807.         beq.s    amb_err
  2808.         move.l    _mixbuffsize-DB(a3),_buffsize-DB(a3)
  2809.         movem.l    (sp)+,d2/a2/a3/a6
  2810.         moveq    #0,d0
  2811.         rts
  2812. amb_err        bsr.s    FreeMixBuffers
  2813.         movem.l    (sp)+,d2/a2/a3/a6
  2814.         moveq    #1,d0
  2815.         rts
  2816.  
  2817. FreeMixBuffers    movem.l    a2/a3/d2/a6,-(sp)
  2818.         lea    DB,a3
  2819.         moveq    #7,d2
  2820.         lea    _chipbuff-DB(a3),a2
  2821.         movea.l    4.w,a6
  2822. 1$        move.l    (a2),a1
  2823.         clr.l    (a2)+
  2824.         jsr    -$2B2(a6)    ;FreeVec
  2825.         dbra    d2,1$
  2826.         move.l    _mixbuff-DB(a3),a1
  2827.         jsr    -$2B2(a6)    ;FreeVec
  2828.         move.l    _mixbuff+4-DB(a3),a1
  2829.         jsr    -$2B2(a6)    ;FreeVec
  2830.         clr.l    _mixbuff-DB(a3)
  2831.         clr.l    _mixbuff+4-DB(a3)
  2832.         clr.l    _buffsize-DB(a3)
  2833.         movem.l    (sp)+,a2/a3/d2/a6
  2834.         rts
  2835.  
  2836. ; InitMix... song ptr in A4, DB in A6
  2837. InitMix:    move.l    a6,-(sp)
  2838.         bsr    AllocMixBuffers
  2839.         tst.l    d0
  2840.         bne.w    initm_err
  2841.         clr.w    _currleft
  2842.         clr.w    _currleftfract
  2843.         bsr    InitFreqTables
  2844.         tst.l    d0
  2845.         bne.w    initm_err
  2846. ; --- set audio hardware
  2847.         lea    $DFF000,a0
  2848.         move.w    #$0780,$9A(a0) ;INTENA
  2849.         move.w    #$F,$96(a0) ;DMACON
  2850.         move.l    #3579545,d0
  2851.         move.l    _mixfreq-DB(a6),d1
  2852.         divu    d1,d0        ;d0 = period
  2853.         move.l    _buffsize-DB(a6),d1
  2854.         lsr.l    #1,d1        ;d1 = buffer length
  2855.         move.w    d1,$A4(a0)
  2856.         move.w    d1,$B4(a0)
  2857.         move.w    d1,$C4(a0)
  2858.         move.w    d1,$D4(a0)
  2859.         move.w    d0,$A6(a0)
  2860.         move.w    d0,$B6(a0)
  2861.         move.w    d0,$C6(a0)
  2862.         move.w    d0,$D6(a0)
  2863.         moveq    #64,d1
  2864.         move.w    d1,$A8(a0)
  2865.         move.w    d1,$B8(a0)
  2866.         tst.b    _mix14bit-DB(a6)
  2867.         beq.s    5$
  2868.         moveq    #1,d1
  2869. 5$        move.w    d1,$C8(a0)
  2870.         move.w    d1,$D8(a0)
  2871.         move.l    #3579545,d1
  2872.         divu    d0,d1
  2873.         move.w    d1,_actualrate_hz-DB(a6)
  2874.         move.w    d1,d0
  2875.         clr.w    d1
  2876.         divu    d0,d1
  2877.         move.w    d1,_actualrate_fract-DB(a6)
  2878. ; --- allocate channel structures (if not already allocated)
  2879.         move.w    msng_channels(a4),d0
  2880.         bne.s    4$
  2881.         moveq    #4,d0    ;0 -> 4
  2882. 4$        cmp.w    _mix_channels-DB(a6),d0
  2883.         beq.s    1$
  2884.         movea.l    a6,a0
  2885.         move.l    a6,-(sp)
  2886.         movea.l    4.w,a6            ;ExecBase
  2887.         jsr    -$78(a6)        ;Disable()
  2888.         movea.l    _chinfo-DB(a0),a1
  2889.         clr.l    _chinfo-DB(a0)
  2890.         jsr    -$7E(a6)        ;Enable()
  2891.         clr.w    _mix_channels-DB(a0)
  2892.         mulu    #ci_sizeof,d0
  2893.         moveq    #1,d1            ;MEMF_PUBLIC
  2894.         jsr    -$2AC(a6)    ;AllocVec
  2895.         movea.l    (sp)+,a6
  2896.         move.l    d0,_chinfo-DB(a6)
  2897.         beq.s    initm_err
  2898.         move.w    msng_channels(a4),_mix_channels-DB(a6)
  2899.         bne.s    1$
  2900.         move.w    #4,_mix_channels-DB(a6)
  2901. 1$        move.w    _mix_channels-DB(a6),d0
  2902.         mulu    #ci_sizeof,d0
  2903.         movea.l    _chinfo-DB(a6),a1
  2904.         movea.l    a1,a0
  2905.         subq.w    #1,d0
  2906. 2$        clr.b    (a1)+
  2907.         dbra    d0,2$
  2908.         move.w    _mix_channels-DB(a6),d0
  2909.         subq.w    #1,d0
  2910. 3$        bset    #CHFLAGB_MUTED,ci_flags(a0)
  2911.         bset    #CHFLAGB_STARTSYN,ci_flags(a0)
  2912.         lea    ci_sizeof(a0),a0
  2913.         dbra    d0,3$
  2914.         bsr.w    FillVolTables
  2915.         tst.l    d0
  2916.         bne.s    initm_err
  2917.         XREF    _SetMixVars
  2918.         jsr    _SetMixVars(pc)
  2919.         movea.l    a4,a0
  2920.         jsr    _SetMixTempo(pc)
  2921.         tst.b    msng_m_echo(a4)
  2922.         beq.s    initm_noecho
  2923.         cmp.b    #2,msng_m_echo(a4)
  2924.         bhi.s    initm_noecho    ;unknown echo type!
  2925.         moveq    #0,d0
  2926.         move.w    msng_m_echolen(a4),d0
  2927.         bsr.w    AllocEchoBuffer
  2928. initm_noecho    move.l    (sp)+,a6
  2929.         moveq    #0,d0
  2930.         rts
  2931. initm_err    bsr.s    StopMix
  2932.         move.l    (sp)+,a6
  2933.         moveq    #1,d0
  2934.         rts
  2935.  
  2936. StopMix:    move.w    #$0080,$DFF09A    ;INTENA = INTF_AUD0
  2937.         move.w    #$F,$DFF096    ;stop audio DMA
  2938.         bsr.w    FreeMixBuffers
  2939.         bra.w    FreeEchoBuffer
  2940.  
  2941.     IFNE    MIDI
  2942. _GetSerial:    movem.l    a5-a6,-(sp)    ;Get serial port for MIDI
  2943.         lea    DB,a5
  2944.         bsr.s    GetSer2
  2945.         tst.l    d0        ;got the port??
  2946.         beq.s    rgser        ;yes
  2947.         movea.l    4.w,a6        ;no..try to flush serial.device:
  2948.         jsr    -$84(a6)        ;Forbid
  2949.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  2950.         lea    serdev-DB(a5),a1    ;"serial.device"
  2951.         jsr    -$114(a6)        ;FindName
  2952.         tst.l    d0
  2953.         beq.s    serdnotf        ;no serial.device!!
  2954.         move.l    d0,a1
  2955.         jsr    -$1b6(a6)        ;RemDevice
  2956. serdnotf:    jsr    -$8a(a6)        ;and Permit
  2957.         bsr.s    GetSer2        ;now try it again...
  2958. rgser:        movem.l    (sp)+,a5-a6
  2959.         rts
  2960.  
  2961. GetSer2:    movea.l    4.w,a6
  2962.         moveq    #0,d0
  2963.         lea    miscresname-DB(a5),a1
  2964.         jsr    -$1f2(a6)    ;OpenResource()
  2965.         move.l    d0,miscresbase-DB(a5)
  2966.         tst.l    d0
  2967.         beq.s    gserror
  2968.         move.l    d0,a6
  2969.         lea    medname-DB(a5),a1
  2970.         moveq    #0,d0        ;serial port
  2971.         jsr    -$6(a6)        ;AllocMiscResource()
  2972.         tst.l    d0
  2973.         bne.s    gserror
  2974.         lea    medname-DB(a5),a1
  2975.         moveq    #1,d0        ;serial bits
  2976.         jsr    -$6(a6)
  2977.         tst.l    d0
  2978.         beq.s    gs2_allocok
  2979.         moveq    #0,d0
  2980.         jsr    -$c(a6)        ;bits failed -> Free serial port
  2981.         bra.s    gserror
  2982. gs2_allocok    move.w    $dff01c,d0
  2983.         btst    #0,d0
  2984.         sne    intrson-DB(a5)
  2985.         moveq    #0,d0        ;TBE
  2986.         lea    serinterrupt-DB(a5),a1
  2987.         move.l    4.w,a6
  2988.         jsr    -$a2(a6)    ;SetIntVector()
  2989.         move.l    d0,prevtbe-DB(a5)
  2990.         move.w    #$8001,$dff09a    ;TBE on
  2991.         move.w    #114,$dff032    ;set baud rate (SERPER)
  2992.         st    serportalloc-DB(a5)
  2993.         moveq    #0,d0
  2994.         rts
  2995. gserror:    moveq    #-1,d0
  2996.         rts
  2997.  
  2998. _FreeSerial:    movem.l    a5-a6,-(sp)
  2999.         lea    DB,a5
  3000.         tst.l    miscresbase-DB(a5)
  3001.         beq.s    retfs
  3002.         tst.b    serportalloc-DB(a5)
  3003.         beq.s    retfs
  3004. wmb_loop    move.w    $dff018,d0    ;WAIT until all data sent
  3005.         btst    #12,d0        ;test TSRE bit of SERDAT
  3006.         beq.s    wmb_loop
  3007.         move.w    #$0001,$dff09a    ;disable TBE
  3008.         movea.l    4.w,a6
  3009.         move.l    prevtbe-DB(a5),a1
  3010.         moveq    #0,d0
  3011.         jsr    -$a2(a6)    ;SetIntVector()
  3012. fs_noptbe    movea.l    miscresbase-DB(a5),a6
  3013.         moveq    #0,d0        ;serial port
  3014.         jsr    -$c(a6)        ;FreeMiscResource()
  3015.         moveq    #1,d0        ;serial bits
  3016.         jsr    -$c(a6)
  3017.         clr.b    serportalloc-DB(a5)
  3018.         clr.b    lastcmdbyte-DB(a5)
  3019. retfs:        movem.l    (sp)+,a5-a6
  3020.         rts
  3021.  
  3022. ; Message number in d0.
  3023. _InitMIDIDump:    tst.b    serportalloc
  3024.         beq.s    idd_rts
  3025.         movem.l    a1/a5/a6,-(sp)    ;a1 = data pointer, d1 = length
  3026.         lea    DB,a5
  3027.         movea.l    4.w,a6            ;ExecBase
  3028.         jsr    -$78(a6)        ;Disable()
  3029.         cmp.w    #16,dqentries-DB(a5)    ;dump queue full?
  3030.         bge.s    idd_exit        ;exit without doing anything
  3031.         lea    dqwriteptr-DB(a5),a1
  3032.         movea.l    (a1),a0
  3033.         move.w    d0,(a0)+        ;store message number
  3034.         cmpa.l    a1,a0            ;queue end?
  3035.         bne.s    idd_noresetbuff
  3036.         lea    dumpqueue-DB(a5),a0    ;reset write pointer
  3037. idd_noresetbuff    move.l    a0,(a1)            ;and write it back.
  3038.         addq.w    #1,dqentries-DB(a5)
  3039.         tst.b    sysx-DB(a5)        ;already sending data?
  3040.         bne.s    idd_exit        ;yes. Don't initiate new send.
  3041.         clr.b    lastcmdbyte-DB(a5)
  3042.         bsr    StartNewDump
  3043.         move.w    $dff018,d0        ;SERDATR
  3044.         btst    #13,d0
  3045.         beq.s    idd_exit
  3046.         move.w    #$8001,$dff09c        ;request TBE
  3047. idd_exit    jsr    -$7e(a6)        ;Enable()
  3048.         movem.l    (sp)+,a1/a5/a6
  3049. idd_rts        rts
  3050.  
  3051. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable..(Interrupts are enabled anyway)
  3052.         move.w    #1,$9c(a0)            ;clear intreq bit
  3053.         tst.b    sysx-buffptr(a1)        ;sysx??
  3054.         bne.s    sih_sysx
  3055.         move.w    bytesinbuff-buffptr(a1),d0    ;bytesinbuff
  3056.         beq.s    exsih                ;buffer empty
  3057.         movea.l    readbuffptr-buffptr(a1),a5    ;get buffer read pointer
  3058.         move.w    #$100,d1            ;Stop bit
  3059.         move.b    (a5)+,d1            ;get byte
  3060.         move.w    d1,$30(a0)            ;and push it to SERDAT
  3061.         cmpa.l    a1,a5                ;shall we reset ptr?
  3062.         bne.s    norrbuffptr            ;not yet..
  3063.         lea    -256(a1),a5
  3064. norrbuffptr    subq.w    #1,d0                ;one less bytes in buffer
  3065.         move.w    d0,bytesinbuff-buffptr(a1)    ;remember it
  3066.         move.l    a5,readbuffptr-buffptr(a1)    ;push new read ptr back
  3067. exsih        move.w    #$c000,$9a(a0)
  3068.         rts
  3069. sih_sysx    move.w    #$100,d1
  3070.         movea.l    sysxptr-buffptr(a1),a5    ;data pointer
  3071.         move.b    (a5)+,d1
  3072.         move.l    a5,sysxptr-buffptr(a1)
  3073.         move.w    d1,$30(a0)        ;-> SERDAT
  3074.         subq.l    #1,sysxleft-buffptr(a1)    ;sub data left length
  3075.         bne.s    exsih        ;not 0w
  3076.         lea    DB,a5
  3077.         clr.b    lastcmdbyte-DB(a5)
  3078.         bsr.s    StartNewDump
  3079.         bra.s    exsih
  3080.  
  3081. StartNewDump:    tst.w    dqentries-DB(a5)    ;queue empty?
  3082.         beq.s    snd_exit2
  3083.         movea.l    dqreadptr-DB(a5),a1    ;get read pointer
  3084.         move.w    (a1)+,d0        ;get message number (D0)
  3085.         cmpa.l    #dqwriteptr,a1        ;queue end?
  3086.         bne.s    snd_noresetbuff
  3087.         lea    dumpqueue-DB(a5),a1    ;reset write pointer
  3088. snd_noresetbuff    move.l    a1,dqreadptr-DB(a5)    ;and write it back.
  3089.         subq.w    #1,dqentries-DB(a5)
  3090. ; then attempt to search the given message (# in D0)
  3091.         move.l    _module-DB(a5),d1
  3092.         beq.s    StartNewDump
  3093.         move.l    d1,a1
  3094.         move.l    mmd_expdata(a1),d1
  3095.         beq.s    StartNewDump
  3096.         move.l    d1,a1
  3097.         move.l    52(a1),d1        ;exp_dump
  3098.         beq.s    StartNewDump
  3099.         move.l    d1,a1
  3100.         cmp.w    (a1),d0
  3101.         bge.s    StartNewDump
  3102.         addq.l    #8,a1            ;points to MMDDump ptr table
  3103.         add.w    d0,d0
  3104.         add.w    d0,d0            ;number *= 4
  3105.         adda.w    d0,a1
  3106.         movea.l    (a1),a1
  3107. ; initialize send variables (msg addr. in A0)
  3108. snd_found    move.l    (a1)+,sysxleft-DB(a5)    ;length
  3109.         move.l    (a1),sysxptr-DB(a5)    ;data pointer
  3110.         st    sysx-DB(a5)
  3111.         rts
  3112. snd_exit2    clr.b    sysx-DB(a5)        ;finish dump
  3113.         rts
  3114.  
  3115. _AddMIDIData    move.l    a6,-(sp)
  3116.         lea    DB,a6
  3117.         bsr.s    _AddMIDId
  3118.         move.l    (sp)+,a6
  3119.         rts
  3120.  
  3121. _AddMIDId    movem.l    a1-a3/a5,-(sp)
  3122.         tst.b    serportalloc-DB(a6)
  3123.         beq.s    retamd1
  3124.         movea.l    4.w,a5
  3125.         lea    $dff09a,a3
  3126.         move.w    #$4000,(a3)    ;Disable interrupts
  3127.         addq.b    #1,$126(a5)    ;ExecBase->IDNestCnt
  3128.         lea    buffptr-DB(a6),a2    ;end of buffer (ptr)
  3129.         move.w    -130(a3),d1    ;-130(a3) = $dff018 (SERDATR)
  3130.         btst    #13,d1
  3131.         beq.s    noTBEreq
  3132.         move.w    #$8001,2(a3)    ;request TBE [2(a3) = $dff09c]
  3133. noTBEreq    movea.l    (a2),a1        ;buffer pointer
  3134.         subq.w    #1,d0        ;-1 for DBF
  3135. adddataloop    move.b    (a0)+,d1    ;get byte
  3136.         bpl.s    norscheck    ;this isn't a status byte
  3137.         cmp.b    #$ef,d1        ;ignore system messages
  3138.         bhi.s    norscheck
  3139.         cmp.b    lastcmdbyte-DB(a6),d1    ;same as previous status byte?
  3140.         beq.s    samesb            ;yes, skip
  3141.         move.b    d1,lastcmdbyte-DB(a6)    ;no, don't skip but store.
  3142. norscheck    move.b    d1,(a1)+        ;push to midi send buffer
  3143.         addq.w    #1,8(a2)
  3144. samesb        cmpa.l    a2,a1            ;end of buffer??
  3145.         bne.s    noresbuffptr        ;no.
  3146.         lea    sendbuffer-DB(a6),a1    ;reset
  3147. noresbuffptr    dbf    d0,adddataloop
  3148.         move.l    a1,(a2)            ;push back new buffer ptr
  3149.         subq.b    #1,$126(a5)
  3150.         bge.s    retamd1
  3151.         move.w    #$c000,(a3)    ;enable interrupts again
  3152. retamd1        movem.l    (sp)+,a1-a3/a5
  3153.         rts
  3154.     ENDC
  3155.  
  3156.         DATA
  3157. DB:        ;Data base pointer
  3158.     IFNE    MIDI
  3159. sendbuffer    ds.b    256
  3160. buffptr        dc.l    sendbuffer
  3161. readbuffptr    dc.l    sendbuffer
  3162. bytesinbuff    dc.w    0
  3163. sysx        dc.b    0
  3164. lastcmdbyte    dc.b    0
  3165. sysxptr        dc.l    0
  3166. sysxleft    dc.l    0
  3167. dumpqueue    ds.w    16
  3168. dqwriteptr    dc.l    dumpqueue
  3169. dqreadptr    dc.l    dumpqueue
  3170. dqentries    dc.w    0
  3171.     ENDC
  3172. miscresbase    dc.l    0
  3173. timerdiv    dc.l    470000
  3174. audiodevopen    dc.b    0
  3175.     IFNE    AUDDEV
  3176. sigbitnum    dc.b    -1
  3177.     ENDC
  3178.     IFNE    MIDI
  3179. serportalloc    dc.b    0
  3180.     ENDC
  3181.         even
  3182.     IFNE    MIDI
  3183. preschgdata    dc.l    0
  3184. noteondata    dc.l    0
  3185.     ENDC
  3186. _module        dc.l    0
  3187.     IFNE    MIDI
  3188. bytesinnotebuff    dc.w    0
  3189. noteonbuff    ds.b    (MAX_NUMTRACKS+2)*3
  3190.         even
  3191. intrson        dc.b    0,0
  3192. prevtbe        dc.l    0
  3193.     ENDC
  3194.     IFNE    MIDI
  3195. serinterrupt    dc.w    0,0,0,0,0
  3196.         dc.l    serintname,buffptr,SerIntHandler
  3197.     ENDC
  3198.     IFNE    AUDDEV
  3199. allocport    dc.l    0,0    ;succ, pred
  3200.         dc.b    4,0    ;NT_MSGPORT
  3201.         dc.l    0    ;name
  3202.         dc.b    0,0    ;flags = PA_SIGNAL
  3203.         dc.l    0    ;task
  3204. reqlist        dc.l    0,0,0    ;list head, tail and tailpred
  3205.         dc.b    5,0
  3206. allocreq    dc.l    0,0
  3207.         dc.b    0,127    ;NT_UNKNOWN, use maximum priority (127)
  3208.         dc.l    0,allocport    ;name, replyport
  3209.         dc.w    68        ;length
  3210.         dc.l    0    ;io_Device
  3211.         dc.l    0    ;io_Unit
  3212.         dc.w    0    ;io_Command
  3213.         dc.b    0,0    ;io_Flags, io_Error
  3214.         dc.w    0    ;ioa_AllocKey
  3215.         dc.l    challocmask    ;ioa_Data
  3216.         dc.l    1    ;ioa_Length
  3217.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  3218.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  3219. audiodevname    dc.b    'audio.device',0
  3220. challocmask    dc.b    $F
  3221.     ENDC
  3222. utilityname    dc.b    'utility.library',0
  3223.     IFNE    MIDI
  3224. serintname    dc.b    'OMEDSerialInterrupt',0
  3225. miscresname    dc.b    'misc.resource',0
  3226. serdev        dc.b    'serial.device',0
  3227. medname        dc.b    'OctaMED Pro modplayer',0
  3228.     ENDC
  3229.         even
  3230.     IFNE    MIDI
  3231. midiresd    dc.b    $e0,$00,$40,$b0,$01,$00
  3232.  
  3233. midicontrnum    ds.b    16
  3234.  
  3235. prevmidicpres    dc.l    0,0,0,0,0,0,0,0 ; 16 * 2 bytes
  3236.  
  3237. ; last MIDI RPN/NRPN (+1, zero = undefined)
  3238. prevmidipn    ds.w    16
  3239. ; last MIDI parameter type: RPN = 0, NRPN = 1
  3240. prevmidiptype    ds.b    16
  3241.  
  3242. prevmidipbend    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3243.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3244.  
  3245. cmd3xsettings    ds.l    15    ;first word = ctrlr type, 2nd word = ctrlr num
  3246. sizeof_mcs    EQU    4    ;the size of an entry
  3247. mcs_type    EQU    0
  3248. mcs_controller    EQU    2
  3249.     ENDC
  3250.  
  3251. ; TRACK-data structures (see definitions at the end of this file)
  3252. trackdatas    ds.b    TRACKDATASZ*64
  3253.         XDEF    trackdataptrs
  3254. ; Build pointer table. This works on Devpac assembler, other assemblers
  3255. ; may need modifications.
  3256. trackdataptrs
  3257. TRKCOUNT    SET    0
  3258.         REPT    64
  3259.         dc.l    trackdatas+TRKCOUNT
  3260. TRKCOUNT    SET    TRKCOUNT+TRACKDATASZ
  3261.         ENDR
  3262.  
  3263. nextblock    dc.b    0 ;\ DON'T SEPARATE
  3264. nxtnoclrln    dc.b    0 ;/
  3265. numtracks    dc.w    0 ;\ DON'T SEPARATE
  3266. numlines    dc.w    0 ;/
  3267. numpages    dc.w    0
  3268. nextblockline    dc.w    0
  3269. rptline        dc.w    0 ;\ DON'T SEPARATE
  3270. rptcounter    dc.w    0 ;/
  3271. blkdelay    dc.w    0    ;block delay (PT PatternDelay)
  3272. fxplineblk    dc.l    0    ;for reading effects
  3273.         XDEF    maxaudiotrk
  3274. maxaudiotrk    dc.w    4    ;max. track number accepting non-MIDI play
  3275.  
  3276. ; Fields in struct InstrExt (easier to access this way rather than
  3277. ; searching through the module).
  3278.         XDEF    flags,rptrptlen
  3279. holdvals    ds.b 63
  3280. decays        ds.b 63
  3281. finetunes    ds.b 63
  3282. flags        ds.b 63
  3283. ext_midipsets    ds.w 63
  3284. outputdevs    ds.b 63
  3285.         CNOP 0,4
  3286. rptrptlen    ds.l 126
  3287.  
  3288. ; ---- user-settable variables
  3289.     XDEF    _mixbuffsize,_mixfreq,_mix14bit
  3290. _mixbuffsize    dc.l    1024
  3291. _mixfreq    dc.l    15000
  3292. _mix14bit    ds.b    1
  3293.         ds.b    3    ;pad
  3294.  
  3295. ; ---- non-user-settable variables
  3296.     XDEF    _chipbuff,_mixbuff,_buffsize,_actualrate_hz
  3297.     XDEF    _actualrate_fract,_chinfo,_freq_tables
  3298.     XDEF    _mix_channels,_echobuffer,_echobuffsz,_voltable
  3299.     XDEF    _echord,_chshift,_sng_struct,UtBase
  3300.     XREF    _currleft,_currleftfract,_passlength,_passfract
  3301. _chipbuff    ds.l    8
  3302. _mixbuff    ds.l    2
  3303. _buffsize    ds.l    1
  3304. _chinfo        ds.l    1
  3305. _frqtblmem    ds.l    1
  3306. _freq_tables    ds.l    16
  3307. _voltable    ds.l    1
  3308. UtBase        ds.l    1
  3309. _echobuffer    ds.l    1
  3310. _echobuffsz    ds.l    1
  3311. _echord        ds.l    1
  3312. _sng_struct    ds.l    1
  3313. _actualrate_hz    dc.w    1
  3314. _actualrate_fract
  3315.         ds.w    1
  3316. _mix_channels    ds.w    1
  3317. _prevnumch    ds.w    1
  3318. _prevadj    ds.w    1
  3319. _chshift    ds.w    1
  3320. _prevstereo    ds.b    1
  3321. _prevfreepan    ds.b    1
  3322.  
  3323.     IFND    __G2
  3324.         section "datachip",data,chip ;for A68k
  3325.     ENDC
  3326.     IFD    __G2
  3327.         section "datachip",data_c ;this is for Devpac 2
  3328.     ENDC
  3329.         XDEF    _modnumm
  3330. _chipzero    dc.l    0
  3331. _modnumm    dc.w    0    ;number of module to play
  3332.         END
  3333.  
  3334.